Ejemplo n.º 1
0
    def _assert_supplemented(self, actual, **kwargs):
        """DRY helper used to verify that program data is extended correctly."""
        course_overview = CourseOverview.get_from_id(self.course.id)  # pylint: disable=no-member
        run_mode = dict(
            factories.RunMode(
                certificate_url=None,
                course_image_url=course_overview.course_image_url,
                course_key=unicode(self.course.id),  # pylint: disable=no-member
                course_url=reverse('course_root', args=[self.course.id]),  # pylint: disable=no-member
                end_date=strftime_localized(self.course.end, 'SHORT_DATE'),
                enrollment_open_date=strftime_localized(utils.DEFAULT_ENROLLMENT_START_DATE, 'SHORT_DATE'),
                is_course_ended=self.course.end < timezone.now(),
                is_enrolled=False,
                is_enrollment_open=True,
                marketing_url=MARKETING_URL,
                start_date=strftime_localized(self.course.start, 'SHORT_DATE'),
                upgrade_url=None,
            ),
            **kwargs
        )
        course_code = factories.CourseCode(display_name=self.course_code['display_name'], run_modes=[run_mode])
        expected = copy.deepcopy(self.program)
        expected['course_codes'] = [course_code]

        self.assertEqual(actual, expected)
Ejemplo n.º 2
0
    def test_expired_course(self):
        """
        Ensure that a user accessing an expired course sees a redirect to
        the student dashboard, not a 404.
        """
        CourseDurationLimitConfig.objects.create(enabled=True, enabled_as_of=datetime(2010, 1, 1))
        course = CourseFactory.create(start=THREE_YEARS_AGO)
        url = course_home_url(course)

        for mode in [CourseMode.AUDIT, CourseMode.VERIFIED]:
            CourseModeFactory.create(course_id=course.id, mode_slug=mode)

        # assert that an if an expired audit user tries to access the course they are redirected to the dashboard
        audit_user = UserFactory(password=self.TEST_PASSWORD)
        self.client.login(username=audit_user.username, password=self.TEST_PASSWORD)
        audit_enrollment = CourseEnrollment.enroll(audit_user, course.id, mode=CourseMode.AUDIT)
        ScheduleFactory(start=THREE_YEARS_AGO, enrollment=audit_enrollment)

        response = self.client.get(url)

        expiration_date = strftime_localized(course.start + timedelta(weeks=4), 'SHORT_DATE')
        expected_params = QueryDict(mutable=True)
        course_name = CourseOverview.get_from_id(course.id).display_name_with_default
        expected_params['access_response_error'] = 'Access to {run} expired on {expiration_date}'.format(
            run=course_name,
            expiration_date=expiration_date
        )
        expected_url = '{url}?{params}'.format(
            url=reverse('dashboard'),
            params=expected_params.urlencode()
        )
        self.assertRedirects(response, expected_url)
Ejemplo n.º 3
0
def get_user_orders(user):
    """Given a user, get the detail of all the orders from the Ecommerce service.

    Args:
        user (User): The user to authenticate as when requesting ecommerce.

    Returns:
        list of dict, representing orders returned by the Ecommerce service.
    """
    user_orders = []
    commerce_configuration = CommerceConfiguration.current()
    user_query = {'username': user.username}

    use_cache = commerce_configuration.is_cache_enabled
    cache_key = commerce_configuration.CACHE_KEY + '.' + str(user.id) if use_cache else None
    api = ecommerce_api_client(user)
    commerce_user_orders = get_edx_api_data(
        commerce_configuration, 'orders', api=api, querystring=user_query, cache_key=cache_key
    )

    for order in commerce_user_orders:
        if order['status'].lower() == 'complete':
            date_placed = datetime.strptime(order['date_placed'], "%Y-%m-%dT%H:%M:%SZ")
            order_data = {
                'number': order['number'],
                'price': order['total_excl_tax'],
                'order_date': strftime_localized(date_placed, 'SHORT_DATE'),
                'receipt_url': EcommerceService().get_receipt_page_url(order['number']),
                'lines': order['lines'],
            }
            user_orders.append(order_data)

    return user_orders
Ejemplo n.º 4
0
def _update_certificate_context(context, course, user_certificate, platform_name):
    """
    Build up the certificate web view context using the provided values
    (Helper method to keep the view clean)
    """
    # Populate dynamic output values using the course/certificate data loaded above
    certificate_type = context.get('certificate_type')

    # Override the defaults with any mode-specific static values
    context['certificate_id_number'] = user_certificate.verify_uuid
    context['certificate_verify_url'] = "{prefix}{uuid}{suffix}".format(
        prefix=context.get('certificate_verify_url_prefix'),
        uuid=user_certificate.verify_uuid,
        suffix=context.get('certificate_verify_url_suffix')
    )

    # Translators:  The format of the date includes the full name of the month
    date = display_date_for_certificate(course, user_certificate)
    context['certificate_date_issued'] = _('{month} {day}, {year}').format(
        month=strftime_localized(date, "%B"),
        day=date.day,
        year=date.year
    )

    # Translators:  This text represents the verification of the certificate
    context['document_meta_description'] = _('This is a valid {platform_name} certificate for {user_name}, '
                                             'who participated in {partner_short_name} {course_number}').format(
        platform_name=platform_name,
        user_name=context['accomplishment_copy_name'],
        partner_short_name=context['organization_short_name'],
        course_number=context['course_number']
    )

    # Translators:  This text is bound to the HTML 'title' element of the page and appears in the browser title bar
    context['document_title'] = _("{partner_short_name} {course_number} Certificate | {platform_name}").format(
        partner_short_name=context['organization_short_name'],
        course_number=context['course_number'],
        platform_name=platform_name
    )

    # Translators:  This text fragment appears after the student's name (displayed in a large font) on the certificate
    # screen.  The text describes the accomplishment represented by the certificate information displayed to the user
    context['accomplishment_copy_description_full'] = _("successfully completed, received a passing grade, and was "
                                                        "awarded this {platform_name} {certificate_type} "
                                                        "Certificate of Completion in ").format(
        platform_name=platform_name,
        certificate_type=context.get("certificate_type"))

    certificate_type_description = get_certificate_description(user_certificate.mode, certificate_type, platform_name)
    if certificate_type_description:
        context['certificate_type_description'] = certificate_type_description

    # Translators: This text describes the purpose (and therefore, value) of a course certificate
    context['certificate_info_description'] = _("{platform_name} acknowledges achievements through "
                                                "certificates, which are awarded for course activities "
                                                "that {platform_name} students complete.").format(
        platform_name=platform_name,
        tos_url=context.get('company_tos_url'),
        verified_cert_url=context.get('company_verified_certificate_url'))
Ejemplo n.º 5
0
def enforce_compliance_on_login(user, password):
    """
    Verify that the user's password is compliant with password policy rules and determine what should be done
    if it is not.

    Raises NonCompliantPasswordException when the password is found to be non-compliant and the compliance deadline
    for the user has been reached. In this case, login should be prevented.

    Raises NonCompliantPasswordWarning when the password is found to be non-compliant and the compliance deadline for
    the user is in the future.

    Returns None when the password is found to be compliant, or when no deadline for compliance has been set for the
    user.

    Important: This method should only be called AFTER the user has been authenticated.
    """
    is_compliant = _check_user_compliance(user, password)
    if is_compliant:
        return

    deadline = _get_compliance_deadline_for_user(user)
    if deadline is None:
        return

    now = datetime.now(pytz.UTC)
    if now >= deadline:
        raise NonCompliantPasswordException(
            HTML(_(
                u'{strong_tag_open}We recently changed our password requirements{strong_tag_close}{break_line_tag}'
                'Your current password does not meet the new security requirements. We just sent a password-reset '
                'message to the email address associated with this account. Thank you for helping us keep your data '
                'safe.'
            )).format(
                strong_tag_open=HTML('<strong>'),
                strong_tag_close=HTML('</strong>'),
                break_line_tag=HTML('<br/>'),
            )
        )
    else:
        raise NonCompliantPasswordWarning(
            HTML(_(
                u'{strong_tag_open}Required Action: Please update your password{strong_tag_close}{break_line_tag}'
                u'As of {deadline}, {platform_name} will require all learners to have complex passwords. Your current '
                u'password does not meet these requirements. To reset your password, go to to '
                u'{anchor_tag_open}Account Settings{anchor_tag_close}.'
            )).format(
                strong_tag_open=HTML('<strong>'),
                strong_tag_close=HTML('</strong>'),
                break_line_tag=HTML('<br/>'),
                platform_name=settings.PLATFORM_NAME,
                deadline=strftime_localized(deadline, DEFAULT_SHORT_DATE_FORMAT),
                anchor_tag_open=HTML(u'<a href="{account_settings_url}">').format(
                    account_settings_url=settings.LMS_ROOT_URL + "/account/settings"
                ),
                anchor_tag_close=HTML('</a>')
            )
        )
Ejemplo n.º 6
0
 def test_non_live_course(self):
     """Ensure that a user accessing a non-live course sees a redirect to
     the student dashboard, not a 404.
     """
     self.setup_user()
     self.enroll(self.course)
     url = reverse('info', args=[unicode(self.course.id)])
     response = self.client.get(url)
     start_date = strftime_localized(self.course.start, 'SHORT_DATE')
     self.assertRedirects(response, '{0}?{1}'.format(reverse('dashboard'), urlencode({'notlive': start_date})))
Ejemplo n.º 7
0
def check_course_access(course, user, action, check_if_enrolled=False, check_survey_complete=True):
    """
    Check that the user has the access to perform the specified action
    on the course (CourseDescriptor|CourseOverview).

    check_if_enrolled: If true, additionally verifies that the user is enrolled.
    check_survey_complete: If true, additionally verifies that the user has completed the survey.
    """
    # Allow staff full access to the course even if not enrolled
    if has_access(user, 'staff', course.id):
        return

    request = get_current_request()
    check_content_start_date_for_masquerade_user(course.id, user, request, course.start)

    access_response = has_access(user, action, course, course.id)
    if not access_response:
        # Redirect if StartDateError
        if isinstance(access_response, StartDateError):
            start_date = strftime_localized(course.start, 'SHORT_DATE')
            params = QueryDict(mutable=True)
            params['notlive'] = start_date
            raise CourseAccessRedirect('{dashboard_url}?{params}'.format(
                dashboard_url=reverse('dashboard'),
                params=params.urlencode()
            ), access_response)

        # Redirect if AuditExpiredError
        if isinstance(access_response, AuditExpiredError):
            params = QueryDict(mutable=True)
            params['access_response_error'] = access_response.additional_context_user_message
            raise CourseAccessRedirect('{dashboard_url}?{params}'.format(
                dashboard_url=reverse('dashboard'),
                params=params.urlencode()
            ), access_response)

        # Redirect if the user must answer a survey before entering the course.
        if isinstance(access_response, MilestoneAccessError):
            raise CourseAccessRedirect('{dashboard_url}'.format(
                dashboard_url=reverse('dashboard'),
            ), access_response)

        # Deliberately return a non-specific error message to avoid
        # leaking info about access control settings
        raise CoursewareAccessException(access_response)

    if check_if_enrolled:
        # If the user is not enrolled, redirect them to the about page
        if not CourseEnrollment.is_enrolled(user, course.id):
            raise CourseAccessRedirect(reverse('about_course', args=[unicode(course.id)]))

    # Redirect if the user must answer a survey before entering the course.
    if check_survey_complete and action == 'load':
        if is_survey_required_and_unanswered(user, course):
            raise CourseAccessRedirect(reverse('course_survey', args=[unicode(course.id)]))
Ejemplo n.º 8
0
def get_expiration_banner_text(user, course, language='en'):
    """
    Get text for banner that messages user course expiration date
    for different tests that depend on it.
    """
    expiration_date = now() + timedelta(weeks=4)
    upgrade_link = verified_upgrade_deadline_link(user=user, course=course)
    enrollment = CourseEnrollment.get_enrollment(user, course.id)
    upgrade_deadline = enrollment.upgrade_deadline
    if upgrade_deadline is None or now() < upgrade_deadline:
        upgrade_deadline = enrollment.course_upgrade_deadline

    date_string = u'<span class="localized-datetime" data-format="shortDate" \
        data-datetime="{formatted_date}" data-language="{language}">{formatted_date_localized}</span>'
    formatted_expiration_date = date_string.format(
        language=language,
        formatted_date=expiration_date.strftime("%Y-%m-%d"),
        formatted_date_localized=strftime_localized(expiration_date, EXPIRATION_DATE_FORMAT_STR)
    )
    if upgrade_deadline:
        formatted_upgrade_deadline = date_string.format(
            language=language,
            formatted_date=upgrade_deadline.strftime("%Y-%m-%d"),
            formatted_date_localized=strftime_localized(upgrade_deadline, EXPIRATION_DATE_FORMAT_STR)
        )

        bannerText = u'<strong>Audit Access Expires {expiration_date}</strong><br>\
                     You lose all access to this course, including your progress, on {expiration_date}.\
                     <br>Upgrade by {upgrade_deadline} to get unlimited access to the course as long as it exists\
                     on the site. <a href="{upgrade_link}">Upgrade now<span class="sr-only"> to retain access past\
                     {expiration_date}</span></a>'.format(
            expiration_date=formatted_expiration_date,
            upgrade_link=upgrade_link,
            upgrade_deadline=formatted_upgrade_deadline
        )
    else:
        bannerText = u'<strong>Audit Access Expires {expiration_date}</strong><br>\
                     You lose all access to this course, including your progress, on {expiration_date}.\
                     '.format(
            expiration_date=formatted_expiration_date
        )
    return bannerText
Ejemplo n.º 9
0
    def test_course_enrollment_status(self, start_offset, end_offset, is_enrollment_open):
        """Verify that course enrollment status is reflected correctly."""
        self.course.enrollment_start = timezone.now() - datetime.timedelta(days=start_offset)
        self.course.enrollment_end = timezone.now() - datetime.timedelta(days=end_offset)
        self.course = self.update_course(self.course, self.user.id)  # pylint: disable=no-member

        data = utils.ProgramDataExtender(self.program, self.user).extend()

        self._assert_supplemented(
            data,
            is_enrollment_open=is_enrollment_open,
            enrollment_open_date=strftime_localized(self.course.enrollment_start, 'SHORT_DATE'),
        )
Ejemplo n.º 10
0
def supplement_program_data(program_data, user):
    """Supplement program course codes with CourseOverview and CourseEnrollment data.

    Arguments:
        program_data (dict): Representation of a program.
        user (User): The user whose enrollments to inspect.
    """
    for organization in program_data['organizations']:
        # TODO cache the results of the get_organization_by_short_name call
        # so we don't have to hit database that frequently
        org_obj = get_organization_by_short_name(organization['key'])
        if org_obj and org_obj.get('logo'):
            organization['img'] = org_obj['logo'].url

    for course_code in program_data['course_codes']:
        for run_mode in course_code['run_modes']:
            course_key = CourseKey.from_string(run_mode['course_key'])
            course_overview = CourseOverview.get_from_id(course_key)

            run_mode['course_url'] = reverse('course_root', args=[course_key])
            run_mode['course_image_url'] = course_overview.course_image_url

            run_mode['start_date'] = course_overview.start_datetime_text()
            run_mode['end_date'] = course_overview.end_datetime_text()

            end_date = course_overview.end or datetime.datetime.max.replace(tzinfo=pytz.UTC)
            run_mode['is_course_ended'] = end_date < timezone.now()

            run_mode['is_enrolled'] = CourseEnrollment.is_enrolled(user, course_key)

            enrollment_start = course_overview.enrollment_start or datetime.datetime.min.replace(tzinfo=pytz.UTC)
            enrollment_end = course_overview.enrollment_end or datetime.datetime.max.replace(tzinfo=pytz.UTC)
            is_enrollment_open = enrollment_start <= timezone.now() < enrollment_end
            run_mode['is_enrollment_open'] = is_enrollment_open
            if not is_enrollment_open:
                # Only render this enrollment open date if the enrollment open is in the future
                run_mode['enrollment_open_date'] = strftime_localized(enrollment_start, 'SHORT_DATE')

            # TODO: Currently unavailable on LMS.
            run_mode['marketing_url'] = ''

            certificate_data = certificate_api.certificate_downloadable_status(user, course_key)
            certificate_uuid = certificate_data.get('uuid')
            if certificate_uuid:
                run_mode['certificate_url'] = certificate_api.get_certificate_url(
                    course_id=course_key,
                    uuid=certificate_uuid,
                )

    return program_data
Ejemplo n.º 11
0
    def test_no_enrollment_start_date(self):
        """Verify that a closed course with no explicit enrollment start date doesn't cause an error.

        Regression test for ECOM-4973.
        """
        self.course.enrollment_end = timezone.now() - datetime.timedelta(days=1)
        self.course = self.update_course(self.course, self.user.id)  # pylint: disable=no-member

        data = utils.supplement_program_data(self.program, self.user)

        self._assert_supplemented(
            data,
            is_enrollment_open=False,
            enrollment_open_date=strftime_localized(utils.DEFAULT_ENROLLMENT_START_DATE, 'SHORT_DATE'),
        )
Ejemplo n.º 12
0
    def to_dict(self):
        """
        Convert entitlement to dictionary representation including relevant policy information.

        Returns:
            The entitlement UUID
            The associated course's UUID
            The date at which the entitlement expired. None if it is still active.
            The localized string representing the date at which the entitlement expires.
        """
        expiration_date = None
        if self.get_days_until_expiration() < settings.ENTITLEMENT_EXPIRED_ALERT_PERIOD:
            expiration_date = strftime_localized(
                now() + timedelta(days=self.get_days_until_expiration()),
                'SHORT_DATE'
            )
        expired_at = strftime_localized(self.expired_at_datetime, 'SHORT_DATE') if self.expired_at_datetime else None

        return {
            'uuid': str(self.uuid),
            'course_uuid': str(self.course_uuid),
            'expired_at': expired_at,
            'expiration_date': expiration_date
        }
Ejemplo n.º 13
0
 def strftime(self, *args, **kwargs):
     """
     A locale-aware implementation of strftime.
     """
     # This is the wrong place to import this function.  I'm putting it here
     # because the xmodule test suite can't import this module, because
     # Django is not available in that suite.  This function isn't called in
     # that suite, so this hides the import so the test won't fail.
     #
     # As I said, this is wrong.  But Cale says this code will soon be
     # refactored to a place that will be right, and the code can be made
     # right there.  If you are reading this comment after April 1, 2014,
     # then Cale was a liar.
     from util.date_utils import strftime_localized
     return strftime_localized(*args, **kwargs)
Ejemplo n.º 14
0
    def strftime(self, *args, **kwargs):
        """
        A locale-aware implementation of strftime.
        """
        # This is the wrong place to import this function.  I'm putting it here
        # because the xmodule test suite can't import this module, because
        # Django is not available in that suite.  This function isn't called in
        # that suite, so this hides the import so the test won't fail.
        #
        # As I said, this is wrong.  But Cale says this code will soon be
        # refactored to a place that will be right, and the code can be made
        # right there.  If you are reading this comment after April 1, 2014,
        # then Cale was a liar.
        from util.date_utils import strftime_localized

        return strftime_localized(*args, **kwargs)
Ejemplo n.º 15
0
    def test_non_live_course(self):
        """
        Ensure that a user accessing a non-live course sees a redirect to
        the student dashboard, not a 404.
        """
        future_course = self.create_future_course()
        self.create_user_for_course(future_course, CourseUserType.ENROLLED)

        url = course_home_url(future_course)
        response = self.client.get(url)
        start_date = strftime_localized(future_course.start, 'SHORT_DATE')
        expected_params = QueryDict(mutable=True)
        expected_params['notlive'] = start_date
        expected_url = '{url}?{params}'.format(
            url=reverse('dashboard'), params=expected_params.urlencode())
        self.assertRedirects(response, expected_url)
Ejemplo n.º 16
0
 def test_non_live_course(self):
     """Ensure that a user accessing a non-live course sees a redirect to
     the student dashboard, not a 404.
     """
     self.setup_user()
     self.enroll(self.course)
     url = reverse('info', args=[text_type(self.course.id)])
     response = self.client.get(url)
     start_date = strftime_localized(self.course.start, 'SHORT_DATE')
     expected_params = QueryDict(mutable=True)
     expected_params['notlive'] = start_date
     expected_url = '{url}?{params}'.format(
         url=reverse('dashboard'),
         params=expected_params.urlencode()
     )
     self.assertRedirects(response, expected_url)
 def test_non_live_course(self):
     """Ensure that a user accessing a non-live course sees a redirect to
     the student dashboard, not a 404.
     """
     self.setup_user()
     self.enroll(self.course)
     url = reverse('info', args=[unicode(self.course.id)])
     response = self.client.get(url)
     start_date = strftime_localized(self.course.start, 'SHORT_DATE')
     expected_params = QueryDict(mutable=True)
     expected_params['notlive'] = start_date
     expected_url = '{url}?{params}'.format(
         url=reverse('dashboard'),
         params=expected_params.urlencode()
     )
     self.assertRedirects(response, expected_url)
Ejemplo n.º 18
0
    def test_course_run_enrollment_status(self, start_offset, end_offset, is_enrollment_open):
        """
        Verify that course run enrollment status is reflected correctly.
        """
        self.course.enrollment_start = datetime.datetime.now(utc) - datetime.timedelta(days=start_offset)
        self.course.enrollment_end = datetime.datetime.now(utc) - datetime.timedelta(days=end_offset)

        self.course = self.update_course(self.course, self.user.id)

        data = ProgramDataExtender(self.program, self.user).extend()

        self._assert_supplemented(
            data,
            is_enrollment_open=is_enrollment_open,
            enrollment_open_date=strftime_localized(self.course.enrollment_start, 'SHORT_DATE'),
        )
Ejemplo n.º 19
0
def enforce_compliance_on_login(user, password):
    """
    Verify that the user's password is compliant with password policy rules and determine what should be done
    if it is not.

    Raises NonCompliantPasswordException when the password is found to be non-compliant and the compliance deadline
    for the user has been reached. In this case, login should be prevented.

    Raises NonCompliantPasswordWarning when the password is found to be non-compliant and the compliance deadline for
    the user is in the future.

    Returns None when the password is found to be compliant, or when no deadline for compliance has been set for the
    user.

    Important: This method should only be called AFTER the user has been authenticated.
    """
    is_compliant = _check_user_compliance(user, password)
    if is_compliant:
        return

    deadline = _get_compliance_deadline_for_user(user)
    if deadline is None:
        return

    now = datetime.now(pytz.UTC)
    if now >= deadline:
        raise NonCompliantPasswordException(
            _capitalize_first(_(
                '{platform_name} now requires more complex passwords. Your current password does not meet the new '
                'requirements. Change your password now using the "Forgot password?" link below to continue using the '
                'site. Thank you for helping us keep your data safe.'
            ).format(
                platform_name=settings.PLATFORM_NAME
            ))
        )
    else:
        raise NonCompliantPasswordWarning(
            _capitalize_first(_(
                '{platform_name} now requires more complex passwords. Your current password does not meet the new '
                'requirements. You must change your password by {deadline} to be able to continue using the site. '
                'To change your password, select the dropdown menu icon next to your username, then select "Account". '
                'You can reset your password from this page. Thank you for helping us keep your data safe.'
            ).format(
                platform_name=settings.PLATFORM_NAME,
                deadline=strftime_localized(deadline, DEFAULT_SHORT_DATE_FORMAT)
            ))
        )
Ejemplo n.º 20
0
def get_user_orders(user):
    """Given a user, get the detail of all the orders from the Ecommerce service.

    Arguments:
        user (User): The user to authenticate as when requesting ecommerce.

    Returns:
        list of dict, representing orders returned by the Ecommerce service.
    """
    no_data = []
    user_orders = []
    allowed_course_modes = ["professional", "verified", "credit"]
    commerce_configuration = CommerceConfiguration.current()
    user_query = {"username": user.username}

    use_cache = commerce_configuration.is_cache_enabled
    cache_key = commerce_configuration.CACHE_KEY + "." + str(user.id) if use_cache else None
    api = ecommerce_api_client(user)
    commerce_user_orders = get_edx_api_data(
        commerce_configuration, user, "orders", api=api, querystring=user_query, cache_key=cache_key
    )

    for order in commerce_user_orders:
        if order["status"].lower() == "complete":
            for line in order["lines"]:
                product = line.get("product")
                if product:
                    for attribute in product["attribute_values"]:
                        if attribute["name"] == "certificate_type" and attribute["value"] in allowed_course_modes:
                            try:
                                date_placed = datetime.strptime(order["date_placed"], "%Y-%m-%dT%H:%M:%SZ")
                                order_data = {
                                    "number": order["number"],
                                    "price": order["total_excl_tax"],
                                    "title": order["lines"][0]["title"],
                                    "order_date": strftime_localized(
                                        date_placed.replace(tzinfo=pytz.UTC), "SHORT_DATE"
                                    ),
                                    "receipt_url": commerce_configuration.receipt_page + order["number"],
                                }
                                user_orders.append(order_data)
                            except KeyError:
                                log.exception("Invalid order structure: %r", order)
                                return no_data

    return user_orders
Ejemplo n.º 21
0
class StrftimeLocalizedTest(unittest.TestCase):
    """
    Tests for strftime_localized.
    """
    @ddt.data(
        ("%Y", "2013"),
        ("%m/%d/%y", "02/14/13"),
        ("hello", "hello"),
        (u'%Y년 %m월 %d일', u"2013년 02월 14일"),
        ("%a, %b %d, %Y", "Thu, Feb 14, 2013"),
        ("%I:%M:%S %p", "04:41:17 PM"),
    )
    def test_usual_strftime_behavior(self, (fmt, expected)):
        dtime = datetime(2013, 02, 14, 16, 41, 17)
        self.assertEqual(expected, strftime_localized(dtime, fmt))
        # strftime doesn't like Unicode, so do the work in UTF8.
        self.assertEqual(expected, dtime.strftime(fmt.encode('utf8')).decode('utf8'))
Ejemplo n.º 22
0
def get_user_orders(user):
    """Given a user, get the detail of all the orders from the Ecommerce service.

    Arguments:
        user (User): The user to authenticate as when requesting ecommerce.

    Returns:
        list of dict, representing orders returned by the Ecommerce service.
    """
    no_data = []
    user_orders = []
    allowed_course_modes = ['professional', 'verified', 'credit']
    commerce_configuration = CommerceConfiguration.current()
    user_query = {'username': user.username}

    use_cache = commerce_configuration.is_cache_enabled
    cache_key = commerce_configuration.CACHE_KEY + '.' + str(user.id) if use_cache else None
    api = ecommerce_api_client(user)
    commerce_user_orders = get_edx_api_data(
        commerce_configuration, user, 'orders', api=api, querystring=user_query, cache_key=cache_key
    )

    for order in commerce_user_orders:
        if order['status'].lower() == 'complete':
            for line in order['lines']:
                product = line.get('product')
                if product:
                    for attribute in product['attribute_values']:
                        if attribute['name'] == 'certificate_type' and attribute['value'] in allowed_course_modes:
                            try:
                                date_placed = datetime.strptime(order['date_placed'], "%Y-%m-%dT%H:%M:%SZ")
                                order_data = {
                                    'number': order['number'],
                                    'price': order['total_excl_tax'],
                                    'title': order['lines'][0]['title'],
                                    'order_date': strftime_localized(
                                        date_placed.replace(tzinfo=pytz.UTC), 'SHORT_DATE'
                                    ),
                                    'receipt_url': commerce_configuration.receipt_page + order['number']
                                }
                                user_orders.append(order_data)
                            except KeyError:
                                log.exception('Invalid order structure: %r', order)
                                return no_data

    return user_orders
Ejemplo n.º 23
0
def _get_asset_json(display_name, date, location, thumbnail_location, locked):
    """
    Helper method for formatting the asset information to send to client.
    """
    asset_url = StaticContent.get_url_path_from_location(location)
    external_url = settings.LMS_BASE + asset_url
    return {
        'display_name': display_name,
        'date_added': strftime_localized(date, "%m %d, %Y %H:%M"),
        'url': asset_url,
        'external_url': external_url,
        'portable_url': StaticContent.get_static_path_from_location(location),
        'thumbnail': StaticContent.get_url_path_from_location(thumbnail_location) if thumbnail_location is not None else None,
        'locked': locked,
        # Needed for Backbone delete/update.
        'id': asset_url
    }
Ejemplo n.º 24
0
def get_user_orders(user):
    """Given a user, get the detail of all the orders from the Ecommerce service.

    Arguments:
        user (User): The user to authenticate as when requesting ecommerce.

    Returns:
        list of dict, representing orders returned by the Ecommerce service.
    """
    no_data = []
    user_orders = []
    allowed_course_modes = ['professional', 'verified', 'credit']
    commerce_configuration = CommerceConfiguration.current()
    user_query = {'username': user.username}

    use_cache = commerce_configuration.is_cache_enabled
    cache_key = commerce_configuration.CACHE_KEY + '.' + str(user.id) if use_cache else None
    api = ecommerce_api_client(user)
    commerce_user_orders = get_edx_api_data(
        commerce_configuration, user, 'orders', api=api, querystring=user_query, cache_key=cache_key
    )

    for order in commerce_user_orders:
        if order['status'].lower() == 'complete':
            for line in order['lines']:
                product = line.get('product')
                if product:
                    for attribute in product['attribute_values']:
                        if attribute['name'] == 'certificate_type' and attribute['value'] in allowed_course_modes:
                            try:
                                date_placed = datetime.strptime(order['date_placed'], "%Y-%m-%dT%H:%M:%SZ")
                                order_data = {
                                    'number': order['number'],
                                    'price': order['total_excl_tax'],
                                    'title': order['lines'][0]['title'],
                                    'order_date': strftime_localized(
                                        date_placed.replace(tzinfo=pytz.UTC), 'SHORT_DATE'
                                    ),
                                    'receipt_url': commerce_configuration.receipt_page + order['number']
                                }
                                user_orders.append(order_data)
                            except KeyError:
                                log.exception('Invalid order structure: %r', order)
                                return no_data

    return user_orders
Ejemplo n.º 25
0
    def test_course_enrollment_status(self, start_offset, end_offset,
                                      is_enrollment_open):
        """Verify that course enrollment status is reflected correctly."""
        self.course.enrollment_start = timezone.now() - datetime.timedelta(
            days=start_offset)
        self.course.enrollment_end = timezone.now() - datetime.timedelta(
            days=end_offset)
        self.course = self.update_course(self.course, self.user.id)  # pylint: disable=no-member

        data = utils.ProgramDataExtender(self.program, self.user).extend()

        self._assert_supplemented(
            data,
            is_enrollment_open=is_enrollment_open,
            enrollment_open_date=strftime_localized(
                self.course.enrollment_start, 'SHORT_DATE'),
        )
Ejemplo n.º 26
0
def get_user_orders(user):
    """Given a user, get the detail of all the orders from the Ecommerce service.

    Args:
        user (User): The user to authenticate as when requesting ecommerce.

    Returns:
        list of dict, representing orders returned by the Ecommerce service.
    """
    user_orders = []
    commerce_configuration = CommerceConfiguration.current()
    user_query = {'username': user.username}

    use_cache = commerce_configuration.is_cache_enabled
    cache_key = commerce_configuration.CACHE_KEY + '.' + str(
        user.id) if use_cache else None
    api = ecommerce_api_client(user)
    commerce_user_orders = get_edx_api_data(commerce_configuration,
                                            'orders',
                                            api=api,
                                            querystring=user_query,
                                            cache_key=cache_key)

    for order in commerce_user_orders:
        if order['status'].lower() == 'complete':
            date_placed = datetime.strptime(order['date_placed'],
                                            "%Y-%m-%dT%H:%M:%SZ")
            order_data = {
                'number':
                order['number'],
                'price':
                order['total_excl_tax'],
                'order_date':
                strftime_localized(date_placed, 'SHORT_DATE'),
                'receipt_url':
                '{url}&username={username}'.format(
                    url=EcommerceService().get_receipt_page_url(
                        order['number']),
                    username=user.username),
                'lines':
                order['lines'],
            }
            user_orders.append(order_data)

    return user_orders
Ejemplo n.º 27
0
 def __init__(self, user, course, expiration_date):
     error_code = "audit_expired"
     developer_message = "User {} had access to {} until {}".format(user, course, expiration_date)
     expiration_date = strftime_localized(expiration_date, DEFAULT_SHORT_DATE_FORMAT)
     user_message = _("Access expired on {expiration_date}").format(expiration_date=expiration_date)
     try:
         course_name = CourseOverview.get_from_id(course.id).display_name_with_default
         additional_context_user_message = _("Access to {course_name} expired on {expiration_date}").format(
             course_name=course_name,
             expiration_date=expiration_date
         )
     except CourseOverview.DoesNotExist:
         additional_context_user_message = _("Access to the course you were looking"
                                             "for expired on {expiration_date}").format(
             expiration_date=expiration_date
         )
     super(AuditExpiredError, self).__init__(error_code, developer_message, user_message,
                                             additional_context_user_message)
Ejemplo n.º 28
0
    def test_non_live_course(self):
        """
        Ensure that a user accessing a non-live course sees a redirect to
        the student dashboard, not a 404.
        """
        future_course = self.create_future_course()
        self.create_user_for_course(future_course, CourseUserType.ENROLLED)

        url = course_home_url(future_course)
        response = self.client.get(url)
        start_date = strftime_localized(future_course.start, 'SHORT_DATE')
        expected_params = QueryDict(mutable=True)
        expected_params['notlive'] = start_date
        expected_url = '{url}?{params}'.format(
            url=reverse('dashboard'),
            params=expected_params.urlencode()
        )
        self.assertRedirects(response, expected_url)
Ejemplo n.º 29
0
 def __init__(self, user, course, expiration_date):
     error_code = "audit_expired"
     developer_message = u"User {} had access to {} until {}".format(user, course, expiration_date)
     expiration_date = strftime_localized(expiration_date, EXPIRATION_DATE_FORMAT_STR)
     user_message = _(u"Access expired on {expiration_date}").format(expiration_date=expiration_date)
     try:
         course_name = course.display_name_with_default
         additional_context_user_message = _(u"Access to {course_name} expired on {expiration_date}").format(
             course_name=course_name,
             expiration_date=expiration_date
         )
     except CourseOverview.DoesNotExist:
         additional_context_user_message = _(u"Access to the course you were looking"
                                             u" for expired on {expiration_date}").format(
             expiration_date=expiration_date
         )
     super(AuditExpiredError, self).__init__(error_code, developer_message, user_message,
                                             additional_context_user_message)
Ejemplo n.º 30
0
 def __init__(self, user, course, expiration_date):
     error_code = "audit_expired"
     developer_message = u"User {} had access to {} until {}".format(user, course, expiration_date)
     language = get_language()
     expiration_date = strftime_localized(expiration_date, EXPIRATION_DATE_FORMAT_STR)
     user_message = _(u"Access expired on {expiration_date}").format(expiration_date=expiration_date)
     try:
         course_name = course.display_name_with_default
         additional_context_user_message = _(u"Access to {course_name} expired on {expiration_date}").format(
             course_name=course_name,
             expiration_date=expiration_date
         )
     except CourseOverview.DoesNotExist:
         additional_context_user_message = _(u"Access to the course you were looking"
                                             u" for expired on {expiration_date}").format(
             expiration_date=expiration_date
         )
     super(AuditExpiredError, self).__init__(error_code, developer_message, user_message,
                                             additional_context_user_message)
Ejemplo n.º 31
0
def check_course_access(course, user, action, check_if_enrolled=False, check_survey_complete=True):
    """
    Check that the user has the access to perform the specified action
    on the course (CourseDescriptor|CourseOverview).

    check_if_enrolled: If true, additionally verifies that the user is enrolled.
    check_survey_complete: If true, additionally verifies that the user has completed the survey.
    """
    # Allow staff full access to the course even if not enrolled
    if has_access(user, 'staff', course.id):
        return

    access_response = has_access(user, action, course, course.id)
    if not access_response:
        # Redirect if StartDateError
        if isinstance(access_response, StartDateError):
            start_date = strftime_localized(course.start, 'SHORT_DATE')
            params = QueryDict(mutable=True)
            params['notlive'] = start_date
            raise CourseAccessRedirect('{dashboard_url}?{params}'.format(
                dashboard_url=reverse('dashboard'),
                params=params.urlencode()
            ), access_response)

        # Redirect if the user must answer a survey before entering the course.
        if isinstance(access_response, MilestoneAccessError):
            raise CourseAccessRedirect('{dashboard_url}'.format(
                dashboard_url=reverse('dashboard'),
            ), access_response)

        # Deliberately return a non-specific error message to avoid
        # leaking info about access control settings
        raise CoursewareAccessException(access_response)

    if check_if_enrolled:
        # If the user is not enrolled, redirect them to the about page
        if not CourseEnrollment.is_enrolled(user, course.id):
            raise CourseAccessRedirect(reverse('about_course', args=[unicode(course.id)]))

    # Redirect if the user must answer a survey before entering the course.
    if check_survey_complete and action == 'load':
        if is_survey_required_and_unanswered(user, course):
            raise CourseAccessRedirect(reverse('course_survey', args=[unicode(course.id)]))
Ejemplo n.º 32
0
    def test_course_run_enrollment_status(self, start_offset, end_offset,
                                          is_enrollment_open):
        """
        Verify that course run enrollment status is reflected correctly.
        """
        self.course.enrollment_start = datetime.datetime.now(
            utc) - datetime.timedelta(days=start_offset)
        self.course.enrollment_end = datetime.datetime.now(
            utc) - datetime.timedelta(days=end_offset)

        self.course = self.update_course(self.course, self.user.id)

        data = ProgramDataExtender(self.program, self.user).extend()

        self._assert_supplemented(
            data,
            is_enrollment_open=is_enrollment_open,
            enrollment_open_date=strftime_localized(
                self.course.enrollment_start, 'SHORT_DATE'),
        )
Ejemplo n.º 33
0
    def _assert_supplemented(self, actual, **kwargs):
        """DRY helper used to verify that program data is extended correctly."""
        course_overview = CourseOverview.get_from_id(self.course.id)  # pylint: disable=no-member
        run_mode = dict(
            {
                'certificate_url':
                None,
                'course_image_url':
                course_overview.course_image_url,
                'course_key':
                unicode(self.course.id),  # pylint: disable=no-member
                'course_url':
                reverse('course_root', args=[self.course.id]),  # pylint: disable=no-member
                'end_date':
                self.course.end.replace(tzinfo=utc),
                'enrollment_open_date':
                strftime_localized(DEFAULT_ENROLLMENT_START_DATE,
                                   'SHORT_DATE'),
                'is_course_ended':
                self.course.end < datetime.datetime.now(utc),
                'is_enrolled':
                False,
                'is_enrollment_open':
                True,
                'marketing_url':
                self.run_mode['marketing_url'],
                'mode_slug':
                'verified',
                'start_date':
                self.course.start.replace(tzinfo=utc),
                'upgrade_url':
                None,
                'advertised_start':
                None,
            },
            **kwargs)

        self.course_code['run_modes'] = [run_mode]
        self.program['course_codes'] = [self.course_code]

        self.assertEqual(actual, self.program)
Ejemplo n.º 34
0
    def _assert_supplemented(self, actual, **kwargs):
        """DRY helper used to verify that program data is extended correctly."""
        self.course_run.update(
            dict(
                {
                    'certificate_url': None,
                    'course_url': reverse('course_root', args=[self.course.id]),
                    'enrollment_open_date': strftime_localized(DEFAULT_ENROLLMENT_START_DATE, 'SHORT_DATE'),
                    'is_course_ended': self.course.end < datetime.datetime.now(utc),
                    'is_enrolled': False,
                    'is_enrollment_open': True,
                    'upgrade_url': None,
                    'advertised_start': None,
                },
                **kwargs
            )
        )

        self.catalog_course['course_runs'] = [self.course_run]
        self.program['courses'] = [self.catalog_course]

        self.assertEqual(actual, self.program)
Ejemplo n.º 35
0
 def __init__(self, user, course, expiration_date):
     error_code = "audit_expired"
     developer_message = "User {} had access to {} until {}".format(
         user, course, expiration_date)
     language = get_language()
     expiration_date = strftime_localized(expiration_date, '%b. %-d, %Y')
     user_message = _("Access expired on {expiration_date}").format(
         expiration_date=expiration_date)
     try:
         course_name = CourseOverview.get_from_id(
             course.id).display_name_with_default
         additional_context_user_message = _(
             "Access to {course_name} expired on {expiration_date}").format(
                 course_name=course_name, expiration_date=expiration_date)
     except CourseOverview.DoesNotExist:
         additional_context_user_message = _(
             "Access to the course you were looking"
             " for expired on {expiration_date}").format(
                 expiration_date=expiration_date)
     super(AuditExpiredError,
           self).__init__(error_code, developer_message, user_message,
                          additional_context_user_message)
Ejemplo n.º 36
0
    def test_expired_course(self):
        """
        Ensure that a user accessing an expired course sees a redirect to
        the student dashboard, not a 404.
        """
        CourseDurationLimitConfig.objects.create(enabled=True,
                                                 enabled_as_of=datetime(
                                                     2010, 1, 1))
        course = CourseFactory.create(start=THREE_YEARS_AGO)
        url = course_home_url(course)

        for mode in [CourseMode.AUDIT, CourseMode.VERIFIED]:
            CourseModeFactory.create(course_id=course.id, mode_slug=mode)

        # assert that an if an expired audit user tries to access the course they are redirected to the dashboard
        audit_user = UserFactory(password=self.TEST_PASSWORD)
        self.client.login(username=audit_user.username,
                          password=self.TEST_PASSWORD)
        audit_enrollment = CourseEnrollment.enroll(audit_user,
                                                   course.id,
                                                   mode=CourseMode.AUDIT)
        audit_enrollment.created = THREE_YEARS_AGO + timedelta(days=1)
        audit_enrollment.save()
        ScheduleFactory(enrollment=audit_enrollment)

        response = self.client.get(url)

        expiration_date = strftime_localized(
            course.start + timedelta(weeks=4) + timedelta(days=1),
            u'%b %-d, %Y')
        expected_params = QueryDict(mutable=True)
        course_name = CourseOverview.get_from_id(
            course.id).display_name_with_default
        expected_params[
            'access_response_error'] = u'Access to {run} expired on {expiration_date}'.format(
                run=course_name, expiration_date=expiration_date)
        expected_url = '{url}?{params}'.format(
            url=reverse('dashboard'), params=expected_params.urlencode())
        self.assertRedirects(response, expected_url)
Ejemplo n.º 37
0
    def _assert_supplemented(self, actual, **kwargs):
        """DRY helper used to verify that program data is extended correctly."""
        self.course_run.update(
            dict(
                {
                    'certificate_url': None,
                    'course_url': reverse('course_root', args=[self.course.id]),
                    'enrollment_open_date': strftime_localized(DEFAULT_ENROLLMENT_START_DATE, 'SHORT_DATE'),
                    'is_course_ended': self.course.end < datetime.datetime.now(utc),
                    'is_enrolled': False,
                    'is_enrollment_open': True,
                    'upgrade_url': None,
                    'advertised_start': None,
                },
                **kwargs
            )
        )

        self.catalog_course['course_runs'] = [self.course_run]
        self.program['courses'] = [self.catalog_course]

        self.assertEqual(actual, self.program)
Ejemplo n.º 38
0
    def get_context_data(self, **kwargs):
        data = super(UniversityIDView, self).get_context_data(**kwargs)

        registration_end_date = None
        terms_and_conditions = None

        university_settings = get_university_settings(self.get_course_key())
        if university_settings:
            terms_and_conditions = university_settings.terms_and_conditions
            final_date = university_settings.registration_end_date
            date = strftime_localized(final_date, format='SHORT_DATE')
            registration_end_date = date.replace('"', '')

        if settings.FEATURES.get('ENABLE_MKTG_SITE'):
            url_to_enroll = marketing_link('COURSES')
        else:
            url_to_enroll = reverse('about_course',
                                    args=[self.get_course_key()])

        data.update({
            'form':
            self.get_form(),
            'has_valid_information':
            has_valid_university_id(self.request.user,
                                    unicode(self.get_course_key())),
            'is_form_disabled':
            is_student_form_disabled(self.request.user, self.get_course_key()),
            'show_enroll_banner':
            self.show_enroll_banner(),
            'terms_conditions':
            terms_and_conditions,
            'registration_end':
            registration_end_date,
            'url_to_enroll':
            url_to_enroll,
        })

        return data
Ejemplo n.º 39
0
    def get_context_data(self, **kwargs):
        data = super(UniversityIDView, self).get_context_data(**kwargs)
        mktg_enabled = settings.FEATURES.get('ENABLE_MKTG_SITE')
        university_settings = self.get_university_settings()
        final_date = university_settings.registration_end_date if university_settings else None

        if final_date:
            date = strftime_localized(final_date, format="SHORT_DATE")
            registration_end_date = date.replace('"', '')
        else:
            registration_end_date = None


        data.update({
            'form': self.get_form(),
            'has_valid_information': has_valid_university_id(self.request.user, self.kwargs['course_id']),
            'is_form_disabled': self.is_form_disabled(),
            'terms_conditions': university_settings.terms_and_conditions if university_settings else None,
            'show_enroll_banner': self.is_not_enrolled(),
            'registration_end': registration_end_date,
            'url_to_enroll': marketing_link('COURSES') if mktg_enabled else reverse(course_about,args=[self.get_course_key()]),
        })

        return data
Ejemplo n.º 40
0
    def test_usual_strftime_behavior(self, (fmt, expected)):
        dtime = datetime(2013, 02, 14, 16, 41, 17)
        self.assertEqual(expected, strftime_localized(dtime, fmt))
        # strftime doesn't like Unicode, so do the work in UTF8.
        self.assertEqual(expected, dtime.strftime(fmt.encode('utf8')).decode('utf8'))

    @ddt.data(
        ("SHORT_DATE", "Feb 14, 2013"),
        ("LONG_DATE", "Thursday, February 14, 2013"),
        ("TIME", "04:41:17 PM"),
        ("DAY_AND_TIME", "Thursday at 4pm"),
        ("%x %X!", "Feb 14, 2013 04:41:17 PM!"),
    )
    def test_shortcuts(self, (fmt, expected)):
        dtime = datetime(2013, 02, 14, 16, 41, 17)
        self.assertEqual(expected, strftime_localized(dtime, fmt))

    @patch('util.date_utils.pgettext', fake_pgettext(translations={
        ("abbreviated month name", "Feb"): "XXfebXX",
        ("month name", "February"): "XXfebruaryXX",
        ("abbreviated weekday name", "Thu"): "XXthuXX",
        ("weekday name", "Thursday"): "XXthursdayXX",
        ("am/pm indicator", "PM"): "XXpmXX",
    }))
    @ddt.data(
        ("SHORT_DATE", "XXfebXX 14, 2013"),
        ("LONG_DATE", "XXthursdayXX, XXfebruaryXX 14, 2013"),
        ("DATE_TIME", "XXfebXX 14, 2013 at 16:41"),
        ("TIME", "04:41:17 XXpmXX"),
        ("%x %X!", "XXfebXX 14, 2013 04:41:17 XXpmXX!"),
    )
Ejemplo n.º 41
0
def generate_course_expired_message(user, course):
    """
    Generate the message for the user course expiration date if it exists.
    """
    if not CourseDurationLimitConfig.enabled_for_enrollment(
            user=user, course_key=course.id):
        return

    expiration_date = get_user_course_expiration_date(user, course)
    if not expiration_date:
        return

    if is_masquerading_as_specific_student(
            user, course.id) and timezone.now() > expiration_date:
        upgrade_message = _(
            'This learner does not have access to this course. '
            u'Their access expired on {expiration_date}.')
        return HTML(upgrade_message).format(expiration_date=strftime_localized(
            expiration_date, EXPIRATION_DATE_FORMAT_STR))
    else:
        enrollment = CourseEnrollment.get_enrollment(user, course.id)
        if enrollment is None:
            return

        upgrade_deadline = enrollment.upgrade_deadline
        now = timezone.now()
        course_upgrade_deadline = enrollment.course_upgrade_deadline
        if (not upgrade_deadline) or (upgrade_deadline < now):
            upgrade_deadline = course_upgrade_deadline

        expiration_message = _(
            u'{strong_open}Audit Access Expires {expiration_date}{strong_close}'
            u'{line_break}You lose all access to this course, including your progress, on '
            u'{expiration_date}.')
        upgrade_deadline_message = _(
            u'{line_break}Upgrade by {upgrade_deadline} to get unlimited access to the course '
            u'as long as it exists on the site. {a_open}Upgrade now{sronly_span_open} to '
            u'retain access past {expiration_date}{span_close}{a_close}')
        full_message = expiration_message
        if upgrade_deadline and now < upgrade_deadline:
            full_message += upgrade_deadline_message
            using_upgrade_messaging = True
        else:
            using_upgrade_messaging = False

        language = get_language()
        date_string = get_date_string()
        formatted_expiration_date = date_string.format(
            language=language,
            formatted_date=expiration_date.strftime("%Y-%m-%d"),
            formatted_date_localized=strftime_localized(
                expiration_date, EXPIRATION_DATE_FORMAT_STR))
        if using_upgrade_messaging:
            formatted_upgrade_deadline = date_string.format(
                language=language,
                formatted_date=upgrade_deadline.strftime("%Y-%m-%d"),
                formatted_date_localized=strftime_localized(
                    upgrade_deadline, EXPIRATION_DATE_FORMAT_STR))

            return HTML(full_message).format(
                a_open=HTML(u'<a href="{upgrade_link}">').format(
                    upgrade_link=verified_upgrade_deadline_link(
                        user=user, course=course)),
                sronly_span_open=HTML('<span class="sr-only">'),
                span_close=HTML('</span>'),
                a_close=HTML('</a>'),
                expiration_date=HTML(formatted_expiration_date),
                strong_open=HTML('<strong>'),
                strong_close=HTML('</strong>'),
                line_break=HTML('<br>'),
                upgrade_deadline=HTML(formatted_upgrade_deadline))

        else:
            return HTML(full_message).format(
                span_close=HTML('</span>'),
                expiration_date=HTML(formatted_expiration_date),
                strong_open=HTML('<strong>'),
                strong_close=HTML('</strong>'),
                line_break=HTML('<br>'),
            )
Ejemplo n.º 42
0
 def _attach_course_run_enrollment_open_date(self, run_mode):
     run_mode['enrollment_open_date'] = strftime_localized(
         self.enrollment_start, 'SHORT_DATE')
Ejemplo n.º 43
0
def render_body(context, **pageargs):
    __M_caller = context.caller_stack._push_frame()
    try:
        __M_locals = __M_dict_builtin(pageargs=pageargs)
        enterprise_customer_name = context.get('enterprise_customer_name',
                                               UNDEFINED)
        enrollment_message = context.get('enrollment_message', UNDEFINED)
        display_sidebar_account_activation_message = context.get(
            'display_sidebar_account_activation_message', UNDEFINED)
        block_courses = context.get('block_courses', UNDEFINED)
        course_enrollments = context.get('course_enrollments', UNDEFINED)
        banner_account_activation_message = context.get(
            'banner_account_activation_message', UNDEFINED)
        static = _mako_get_namespace(context, 'static')
        unicode = context.get('unicode', UNDEFINED)
        resume_button_urls = context.get('resume_button_urls', UNDEFINED)
        isinstance = context.get('isinstance', UNDEFINED)
        redirect_message = context.get('redirect_message', UNDEFINED)
        show_email_settings_for = context.get('show_email_settings_for',
                                              UNDEFINED)
        empty_dashboard_message = context.get('empty_dashboard_message',
                                              UNDEFINED)
        unfulfilled_entitlement_pseudo_sessions = context.get(
            'unfulfilled_entitlement_pseudo_sessions', UNDEFINED)
        errored_courses = context.get('errored_courses', UNDEFINED)

        def js_extra():
            return render_js_extra(context._locals(__M_locals))

        credit_statuses = context.get('credit_statuses', UNDEFINED)
        display_course_modes_on_dashboard = context.get(
            'display_course_modes_on_dashboard', UNDEFINED)
        account_activation_messages = context.get(
            'account_activation_messages', UNDEFINED)
        staff_access = context.get('staff_access', UNDEFINED)
        marketing_link = context.get('marketing_link', UNDEFINED)
        display_dashboard_courses = context.get('display_dashboard_courses',
                                                UNDEFINED)
        getattr = context.get('getattr', UNDEFINED)
        course_entitlement_available_sessions = context.get(
            'course_entitlement_available_sessions', UNDEFINED)
        len = context.get('len', UNDEFINED)
        enumerate = context.get('enumerate', UNDEFINED)
        consent_required_courses = context.get('consent_required_courses',
                                               UNDEFINED)
        all_course_modes = context.get('all_course_modes', UNDEFINED)
        user = context.get('user', UNDEFINED)
        activate_account_message = context.get('activate_account_message',
                                               UNDEFINED)
        courses_requirements_not_met = context.get(
            'courses_requirements_not_met', UNDEFINED)
        order_history_list = context.get('order_history_list', UNDEFINED)

        def bodyclass():
            return render_bodyclass(context._locals(__M_locals))

        display_sidebar_on_dashboard = context.get(
            'display_sidebar_on_dashboard', UNDEFINED)
        cert_statuses = context.get('cert_statuses', UNDEFINED)
        unfulfilled_entitlement = context.get('unfulfilled_entitlement',
                                              UNDEFINED)
        settings = context.get('settings', UNDEFINED)
        enterprise_message = context.get('enterprise_message', UNDEFINED)
        show_courseware_links_for = context.get('show_courseware_links_for',
                                                UNDEFINED)
        str = context.get('str', UNDEFINED)
        verification_status_by_course = context.get(
            'verification_status_by_course', UNDEFINED)
        course_entitlements = context.get('course_entitlements', UNDEFINED)

        def header_extras():
            return render_header_extras(context._locals(__M_locals))

        inverted_programs = context.get('inverted_programs', UNDEFINED)

        def pagetitle():
            return render_pagetitle(context._locals(__M_locals))

        enrolled_courses_either_paid = context.get(
            'enrolled_courses_either_paid', UNDEFINED)
        __M_writer = context.writer()
        __M_writer(u'\n')
        __M_writer(u'\n')
        __M_writer(u'\n')
        __M_writer(u'\n')
        __M_writer(u'\n\n')

        cert_name_short = settings.CERT_NAME_SHORT
        cert_name_long = settings.CERT_NAME_LONG

        __M_locals_builtin_stored = __M_locals_builtin()
        __M_locals.update(
            __M_dict_builtin([
                (__M_key, __M_locals_builtin_stored[__M_key])
                for __M_key in ['cert_name_long', 'cert_name_short']
                if __M_key in __M_locals_builtin_stored
            ]))
        __M_writer(u'\n\n\n')
        if 'parent' not in context._data or not hasattr(
                context._data['parent'], 'pagetitle'):
            context['self'].pagetitle(**pageargs)

        __M_writer(u'\n')
        if 'parent' not in context._data or not hasattr(
                context._data['parent'], 'bodyclass'):
            context['self'].bodyclass(**pageargs)

        __M_writer(u'\n\n')
        if 'parent' not in context._data or not hasattr(
                context._data['parent'], 'header_extras'):
            context['self'].header_extras(**pageargs)

        __M_writer(u'\n\n')
        if 'parent' not in context._data or not hasattr(
                context._data['parent'], 'js_extra'):
            context['self'].js_extra(**pageargs)

        __M_writer(
            u'\n\n<div class="dashboard-notifications" tabindex="-1">\n\n')
        if banner_account_activation_message:
            __M_writer(u'        <div class="dashboard-banner">\n            ')
            __M_writer(filters.decode.utf8(banner_account_activation_message))
            __M_writer(u'\n        </div>\n')
        __M_writer(u'\n')
        if enrollment_message:
            __M_writer(u'        <div class="dashboard-banner">\n            ')
            __M_writer(filters.decode.utf8(enrollment_message))
            __M_writer(u'\n        </div>\n')
        __M_writer(u'\n')
        if enterprise_message:
            __M_writer(u'        <div class="dashboard-banner">\n            ')
            __M_writer(filters.decode.utf8(enterprise_message))
            __M_writer(u'\n        </div>\n')
        __M_writer(u'\n')
        if account_activation_messages:
            __M_writer(u'      <div class="activation-message-container">\n')
            for account_activation_message in account_activation_messages:
                __M_writer(u'          <div class="account-activation ')
                __M_writer(
                    filters.html_escape(
                        filters.decode.utf8(account_activation_message.tags)))
                __M_writer(
                    u'" role="alert" aria-label="Account Activation Message" tabindex="-1">\n            <div class="message-copy" >\n              '
                )
                __M_writer(filters.decode.utf8(account_activation_message))
                __M_writer(u'\n            </div>\n          </div>\n')
            __M_writer(u'      </div>\n')
        __M_writer(
            u'\n</div>\n\n<main id="main" aria-label="Content" tabindex="-1">\n    <div class="dashboard holder" id="dashboard-main">\n      <div class="main-container">\n        <div class="my-courses" id="my-courses">\n'
        )
        if display_dashboard_courses:
            __M_writer(u'          ')
            runtime._include_file(
                context,
                u'learner_dashboard/_dashboard_navigation_courses.html',
                _template_uri)
            __M_writer(u'\n')
        __M_writer(u'\n')
        if len(course_entitlements + course_enrollments) > 0:
            __M_writer(
                u'            <ul class="listing-courses">\n            ')

            share_settings = configuration_helpers.get_value(
                'SOCIAL_SHARING_SETTINGS',
                getattr(settings, 'SOCIAL_SHARING_SETTINGS', {}))

            __M_locals_builtin_stored = __M_locals_builtin()
            __M_locals.update(
                __M_dict_builtin([(__M_key, __M_locals_builtin_stored[__M_key])
                                  for __M_key in ['share_settings']
                                  if __M_key in __M_locals_builtin_stored]))
            __M_writer(u'\n')
            for dashboard_index, enrollment in enumerate(course_entitlements +
                                                         course_enrollments):
                __M_writer(u'              ')

                # Check if the course run is an entitlement and if it has an associated session
                entitlement = enrollment if isinstance(
                    enrollment, CourseEntitlement) else None
                entitlement_session = entitlement.enrollment_course_run if entitlement else None
                entitlement_days_until_expiration = entitlement.get_days_until_expiration(
                ) if entitlement else None
                entitlement_expiration = datetime.now(tz=pytz.UTC) + timedelta(
                    days=entitlement_days_until_expiration) if (
                        entitlement and entitlement_days_until_expiration <
                        settings.ENTITLEMENT_EXPIRED_ALERT_PERIOD) else None
                entitlement_expiration_date = strftime_localized(
                    entitlement_expiration, 'SHORT_DATE'
                ) if entitlement and entitlement_expiration else None
                entitlement_expired_at = strftime_localized(
                    entitlement.expired_at_datetime, 'SHORT_DATE'
                ) if entitlement and entitlement.expired_at_datetime else None

                is_fulfilled_entitlement = True if entitlement and entitlement_session else False
                is_unfulfilled_entitlement = True if entitlement and not entitlement_session else False

                entitlement_available_sessions = []
                if entitlement:
                    # Grab the available, enrollable sessions for a given entitlement and scrape them for relevant attributes
                    entitlement_available_sessions = [{
                        'session_id':
                        course['key'],
                        'enrollment_end':
                        course['enrollment_end'],
                        'pacing_type':
                        course['pacing_type'],
                        'advertised_start':
                        CourseOverview.get_from_id(
                            CourseKey.from_string(
                                course['key'])).advertised_start,
                        'start':
                        CourseOverview.get_from_id(
                            CourseKey.from_string(course['key'])).start,
                        'end':
                        CourseOverview.get_from_id(
                            CourseKey.from_string(course['key'])).end,
                    } for course in course_entitlement_available_sessions[str(
                        entitlement.uuid)]]
                    if is_fulfilled_entitlement:
                        # If the user has a fulfilled entitlement, pass through the entitlements CourseEnrollment object
                        enrollment = entitlement_session
                    else:
                        # If the user has an unfulfilled entitlement, pass through a bare CourseEnrollment object to populate card with metadata
                        pseudo_session = unfulfilled_entitlement_pseudo_sessions[
                            str(entitlement.uuid)]
                        if not pseudo_session:
                            continue
                        enrollment = CourseEnrollment(
                            user=user,
                            course_id=pseudo_session['key'],
                            mode=pseudo_session['type'])
                    # We only show email settings for entitlement cards if the entitlement has an associated enrollment
                    show_email_settings = is_fulfilled_entitlement and (
                        entitlement_session.course_id
                        in show_email_settings_for)
                else:
                    show_email_settings = (enrollment.course_id
                                           in show_email_settings_for)

                session_id = enrollment.course_id
                show_courseware_link = (session_id
                                        in show_courseware_links_for)
                cert_status = cert_statuses.get(session_id)
                can_refund_entitlement = entitlement and entitlement.is_entitlement_refundable(
                )
                can_unenroll = (not cert_status) or cert_status.get(
                    'can_unenroll') if not unfulfilled_entitlement else False
                credit_status = credit_statuses.get(session_id)
                course_mode_info = all_course_modes.get(session_id)
                is_paid_course = True if entitlement else (
                    session_id in enrolled_courses_either_paid)
                is_course_blocked = (session_id in block_courses)
                course_verification_status = verification_status_by_course.get(
                    session_id, {})
                course_requirements = courses_requirements_not_met.get(
                    session_id)
                related_programs = inverted_programs.get(
                    unicode(entitlement.course_uuid
                            if is_unfulfilled_entitlement else session_id))
                show_consent_link = (session_id in consent_required_courses)
                course_overview = enrollment.course_overview
                resume_button_url = resume_button_urls[dashboard_index]

                __M_locals_builtin_stored = __M_locals_builtin()
                __M_locals.update(
                    __M_dict_builtin([
                        (__M_key, __M_locals_builtin_stored[__M_key])
                        for __M_key in [
                            'course_overview', 'is_course_blocked', 'course',
                            'is_unfulfilled_entitlement',
                            'entitlement_session', 'can_unenroll',
                            'pseudo_session', 'entitlement',
                            'related_programs', 'credit_status',
                            'is_paid_course', 'course_verification_status',
                            'can_refund_entitlement', 'resume_button_url',
                            'show_courseware_link', 'course_requirements',
                            'entitlement_days_until_expiration',
                            'entitlement_available_sessions', 'cert_status',
                            'show_email_settings', 'is_fulfilled_entitlement',
                            'show_consent_link', 'entitlement_expiration',
                            'course_mode_info', 'entitlement_expired_at',
                            'session_id', 'entitlement_expiration_date',
                            'enrollment'
                        ] if __M_key in __M_locals_builtin_stored
                    ]))
                __M_writer(u'\n              ')
                runtime._include_file(
                    context,
                    u'dashboard/_dashboard_course_listing.html',
                    _template_uri,
                    course_overview=course_overview,
                    course_card_index=dashboard_index,
                    enrollment=enrollment,
                    is_unfulfilled_entitlement=is_unfulfilled_entitlement,
                    is_fulfilled_entitlement=is_fulfilled_entitlement,
                    entitlement=entitlement,
                    entitlement_session=entitlement_session,
                    entitlement_available_sessions=
                    entitlement_available_sessions,
                    entitlement_expiration_date=entitlement_expiration_date,
                    entitlement_expired_at=entitlement_expired_at,
                    show_courseware_link=show_courseware_link,
                    cert_status=cert_status,
                    can_refund_entitlement=can_refund_entitlement,
                    can_unenroll=can_unenroll,
                    credit_status=credit_status,
                    show_email_settings=show_email_settings,
                    course_mode_info=course_mode_info,
                    is_paid_course=is_paid_course,
                    is_course_blocked=is_course_blocked,
                    verification_status=course_verification_status,
                    course_requirements=course_requirements,
                    dashboard_index=dashboard_index,
                    share_settings=share_settings,
                    user=user,
                    related_programs=related_programs,
                    display_course_modes_on_dashboard=
                    display_course_modes_on_dashboard,
                    show_consent_link=show_consent_link,
                    enterprise_customer_name=enterprise_customer_name,
                    resume_button_url=resume_button_url)
                __M_writer(u'\n')
            __M_writer(u'\n            </ul>\n')
        else:
            __M_writer(u'            <div class="empty-dashboard-message">\n')
            if display_dashboard_courses:
                __M_writer(u'                <p>')
                __M_writer(
                    filters.html_escape(
                        filters.decode.utf8(
                            _("You are not enrolled in any courses yet."))))
                __M_writer(u'</p>\n')
                if empty_dashboard_message:
                    __M_writer(u'                  <p class="custom-message">')
                    __M_writer(filters.decode.utf8(empty_dashboard_message))
                    __M_writer(u'</p>\n')
                if settings.FEATURES.get('COURSES_ARE_BROWSABLE'):
                    __M_writer(
                        u'                  <a class="btn btn-primary" href="')
                    __M_writer(
                        filters.html_escape(
                            filters.decode.utf8(marketing_link('COURSES'))))
                    __M_writer(u'">\n                    ')
                    __M_writer(
                        filters.html_escape(
                            filters.decode.utf8(_("Explore courses"))))
                    __M_writer(u'\n                  </a>\n')
            else:
                __M_writer(u'              <p>')
                __M_writer(
                    filters.html_escape(
                        filters.decode.utf8(_("Activate your account!"))))
                __M_writer(u'</p>\n              <p class="custom-message">')
                __M_writer(filters.decode.utf8(activate_account_message))
                __M_writer(u'</p>\n')
            __M_writer(u'          </div>\n')
        __M_writer(u'\n')
        if staff_access and len(errored_courses) > 0:
            __M_writer(
                u'            <div id="course-errors">\n              <h2>')
            __M_writer(
                filters.html_escape(
                    filters.decode.utf8(_("Course-loading errors"))))
            __M_writer(u'</h2>\n\n')
            for course_dir, errors in errored_courses.items():
                __M_writer(u'               <h3>')
                __M_writer(filters.html_escape(
                    filters.decode.utf8(course_dir)))
                __M_writer(u'</h3>\n                   <ul>\n')
                for (msg, err) in errors:
                    __M_writer(u'                     <li>')
                    __M_writer(filters.html_escape(filters.decode.utf8(msg)))
                    __M_writer(u'\n                       <ul><li><pre>')
                    __M_writer(filters.html_escape(filters.decode.utf8(err)))
                    __M_writer(
                        u'</pre></li></ul>\n                     </li>\n')
                __M_writer(u'                   </ul>\n')
            __M_writer(u'            </div>\n')
        __M_writer(
            u'        </div>\n      </div>\n      <div class="side-container">\n'
        )
        if display_sidebar_account_activation_message:
            __M_writer(
                u'          <div class="sidebar-notification">\n            ')
            runtime._include_file(context, (static.get_template_path(
                'registration/account_activation_sidebar_notice.html')),
                                  _template_uri)
            __M_writer(u'\n          </div>\n')
        __M_writer(u'\n')
        if settings.FEATURES.get('ENABLE_DASHBOARD_SEARCH'):
            __M_writer(
                u'          <div id="dashboard-search-bar" class="search-bar dashboard-search-bar" role="search" aria-label="Dashboard">\n            <form class="search-form">\n              <label for="dashboard-search-input">'
            )
            __M_writer(
                filters.html_escape(
                    filters.decode.utf8(_("Search Your Courses"))))
            __M_writer(
                u'</label>\n              <div class="search-field-wrapper">\n                <input id="dashboard-search-input" type="text" class="search-field"/>\n                <button type="submit" class="search-button" title="'
            )
            __M_writer(filters.html_escape(filters.decode.utf8(_('Search'))))
            __M_writer(
                u'">\n                  <span class="icon fa fa-search" aria-hidden="true"></span>\n                </button>\n                <button type="button" class="cancel-button" title="'
            )
            __M_writer(
                filters.html_escape(filters.decode.utf8(_('Clear search'))))
            __M_writer(
                u'">\n                  <span class="icon fa fa-remove" aria-hidden="true"></span>\n                </button>\n              </div>\n            </form>\n          </div>\n          <div id="dashboard-search-results" class="search-results dashboard-search-results"></div>\n'
            )
        __M_writer(u'\n')
        if display_sidebar_on_dashboard:
            __M_writer(
                u'          <div class="profile-sidebar" id="profile-sidebar" role="region" aria-label="Account Status Info">\n            <header class="profile">\n              <h2 class="account-status-title sr">'
            )
            __M_writer(
                filters.html_escape(
                    filters.decode.utf8(_("Account Status Info"))))
            __M_writer(
                u': </h2>\n            </header>\n            <div class="user-info">\n              <ul>\n\n'
            )
            if len(order_history_list):
                __M_writer(
                    u'                <li class="order-history">\n                  <span class="title">'
                )
                __M_writer(
                    filters.html_escape(filters.decode.utf8(
                        _("Order History"))))
                __M_writer(u'</span>\n')
                for order_history_item in order_history_list:
                    __M_writer(u'                    <span><a href="')
                    __M_writer(
                        filters.html_escape(
                            filters.decode.utf8(
                                order_history_item['receipt_url'])))
                    __M_writer(u'" target="_blank" class="edit-name">')
                    __M_writer(
                        filters.html_escape(
                            filters.decode.utf8(
                                order_history_item['order_date'])))
                    __M_writer(u'</a></span>\n')
                __M_writer(u'                </li>\n')
            __M_writer(u'\n                ')
            runtime._include_file(context, (static.get_template_path(
                'dashboard/_dashboard_status_verification.html')),
                                  _template_uri)
            __M_writer(
                u'\n\n              </ul>\n            </div>\n          </div>\n'
            )
        __M_writer(
            u'      </div>\n    </div>\n</main>\n\n<div id="email-settings-modal" class="modal" aria-hidden="true">\n  <div class="inner-wrapper" role="dialog" aria-labelledby="email-settings-title">\n    <button class="close-modal">\n      <span class="icon fa fa-remove" aria-hidden="true"></span>\n      <span class="sr">\n'
        )
        __M_writer(u'        ')
        __M_writer(filters.html_escape(filters.decode.utf8(_("Close"))))
        __M_writer(
            u'\n      </span>\n    </button>\n\n    <header>\n      <h2 id="email-settings-title">\n        '
        )
        __M_writer(
            filters.html_escape(
                filters.decode.utf8(
                    Text(_("Email Settings for {course_number}")).
                    format(course_number=HTML(
                        '<span id="email_settings_course_number"></span>')))))
        __M_writer(u'\n        <span class="sr">,\n')
        __M_writer(u'          ')
        __M_writer(filters.html_escape(filters.decode.utf8(_("window open"))))
        __M_writer(
            u'\n        </span>\n      </h2>\n      <hr/>\n    </header>\n\n    <form id="email_settings_form" method="post">\n      <input name="course_id" id="email_settings_course_id" type="hidden" />\n      <label><input type="checkbox" id="receive_emails" name="receive_emails" />'
        )
        __M_writer(
            filters.html_escape(filters.decode.utf8(
                _("Receive course emails"))))
        __M_writer(
            u' </label>\n      <div class="submit">\n        <input type="submit" id="submit" value="'
        )
        __M_writer(filters.html_escape(filters.decode.utf8(
            _('Save Settings'))))
        __M_writer(
            u'" />\n      </div>\n    </form>\n  </div>\n</div>\n\n<div id="unenroll-modal" class="modal unenroll-modal" aria-hidden="true">\n  <div class="inner-wrapper" role="dialog" aria-labelledby="unenrollment-modal-title" aria-live="polite">\n    <button class="close-modal">\n      <span class="icon fa fa-remove" aria-hidden="true"></span>\n      <span class="sr">\n'
        )
        __M_writer(u'        ')
        __M_writer(filters.html_escape(filters.decode.utf8(_("Close"))))
        __M_writer(
            u'\n      </span>\n    </button>\n\n    <header class="unenroll-header">\n      <h2 id="unenrollment-modal-title">\n        <span id=\'track-info\'></span>\n        <span id=\'refund-info\'></span>\n        <span class="sr">,\n'
        )
        __M_writer(u'          ')
        __M_writer(filters.html_escape(filters.decode.utf8(_("window open"))))
        __M_writer(
            u'\n        </span>\n      </h2>\n      <hr/>\n    </header>\n    <div id="unenroll_error" class="modal-form-error"></div>\n    <form id="unenroll_form" method="post" data-remote="true" action="'
        )
        __M_writer(
            filters.html_escape(
                filters.decode.utf8(reverse('change_enrollment'))))
        __M_writer(
            u'">\n      <input name="course_id" id="unenroll_course_id" type="hidden" />\n      <input name="enrollment_action" type="hidden" value="unenroll" />\n      <div class="submit">\n        <input class="submit-button" name="submit" type="submit" value="'
        )
        __M_writer(filters.html_escape(filters.decode.utf8(_('Unenroll'))))
        __M_writer(u'" />\n      </div>\n    </form>\n  </div>\n</div>\n\n')
        runtime._include_file(
            context,
            u'dashboard/_dashboard_entitlement_unenrollment_modal.html',
            _template_uri)
        __M_writer(u'\n')
        return ''
    finally:
        context.caller_stack._pop_frame()
Ejemplo n.º 44
0
 def format_date(date):
     return strftime_localized(date, u'%b %-d, %Y')
Ejemplo n.º 45
0
def register_course_expired_message(request, course):
    """
    Add a banner notifying the user of the user course expiration date if it exists.
    """
    if not CourseDurationLimitConfig.enabled_for_enrollment(user=request.user, course_key=course.id):
        return

    expiration_date = get_user_course_expiration_date(request.user, course)
    if not expiration_date:
        return

    if is_masquerading_as_student(request.user, course.id) and timezone.now() > expiration_date:
        upgrade_message = _('This learner does not have access to this course. '
                            'Their access expired on {expiration_date}.')
        PageLevelMessages.register_warning_message(
            request,
            HTML(upgrade_message).format(
                expiration_date=strftime_localized(expiration_date, '%b. %-d, %Y')
            )
        )
    else:
        enrollment = CourseEnrollment.get_enrollment(request.user, course.id)
        if enrollment is None:
            return

        upgrade_deadline = enrollment.upgrade_deadline
        now = timezone.now()
        course_upgrade_deadline = enrollment.course_upgrade_deadline
        if upgrade_deadline and now > upgrade_deadline:
            upgrade_deadline = course_upgrade_deadline

        expiration_message = _('{strong_open}Audit Access Expires {expiration_date}{strong_close}'
                               '{line_break}You lose all access to this course, including your progress, on '
                               '{expiration_date}.')
        upgrade_deadline_message = _('{line_break}Upgrade by {upgrade_deadline} to get unlimited access to the course '
                                     'as long as it exists on the site. {a_open}Upgrade now{sronly_span_open} to '
                                     'retain access past {expiration_date}{span_close}{a_close}')
        full_message = expiration_message
        if course_upgrade_deadline and now < course_upgrade_deadline:
            full_message += upgrade_deadline_message

        language = get_language()
        language_is_es = language and language.split('-')[0].lower() == 'es'
        if language_is_es:
            formatted_expiration_date = strftime_localized(expiration_date, '%-d de %b. de %Y').lower()
        else:
            formatted_expiration_date = strftime_localized(expiration_date, '%b. %-d, %Y')

        if upgrade_deadline:
            if language_is_es:
                formatted_upgrade_deadline = strftime_localized(upgrade_deadline, '%-d de %b. de %Y').lower()
            else:
                formatted_upgrade_deadline = strftime_localized(upgrade_deadline, '%b. %-d, %Y')

        if upgrade_deadline:
            PageLevelMessages.register_info_message(
                request,
                Text(full_message).format(
                    a_open=HTML('<a href="{upgrade_link}">').format(
                        upgrade_link=verified_upgrade_deadline_link(user=request.user, course=course)
                    ),
                    sronly_span_open=HTML('<span class="sr-only">'),
                    span_close=HTML('</span>'),
                    a_close=HTML('</a>'),
                    expiration_date=formatted_expiration_date,
                    strong_open=HTML('<strong>'),
                    strong_close=HTML('</strong>'),
                    line_break=HTML('<br>'),
                    upgrade_deadline=formatted_upgrade_deadline
                )
            )
        else:
            PageLevelMessages.register_info_message(
                request,
                Text(full_message).format(
                    span_close=HTML('</span>'),
                    expiration_date=formatted_expiration_date,
                    strong_open=HTML('<strong>'),
                    strong_close=HTML('</strong>'),
                    line_break=HTML('<br>'),
                )
            )
Ejemplo n.º 46
0
 def test_translated_formats(self, fmt_expected):
     (fmt, expected) = fmt_expected
     dtime = datetime(2013, 2, 14, 16, 41, 17)
     self.assertEqual(expected, strftime_localized(dtime, fmt))
Ejemplo n.º 47
0
 def test_invalid_format_strings(self, fmt):
     dtime = datetime(2013, 02, 14, 16, 41, 17)
     with self.assertRaises(ValueError):
         strftime_localized(dtime, fmt)
Ejemplo n.º 48
0
 def test_shortcuts(self, fmt_expected):
     (fmt, expected) = fmt_expected
     dtime = datetime(2013, 02, 14, 16, 41, 17)
     self.assertEqual(expected, strftime_localized(dtime, fmt))
Ejemplo n.º 49
0
 def format_date(date):
     return strftime_localized(date, u'%b %-d, %Y')
Ejemplo n.º 50
0
 def strftime(self, *args, **kwargs):
     return strftime_localized(*args, **kwargs)
Ejemplo n.º 51
0
 def test_recursion_protection(self, fmt_expected):
     (fmt, expected) = fmt_expected
     dtime = datetime(2013, 02, 14, 16, 41, 17)
     self.assertEqual(expected, strftime_localized(dtime, fmt))
Ejemplo n.º 52
0
 def strftime(self, *args, **kwargs):
     return strftime_localized(*args, **kwargs)
Ejemplo n.º 53
0
 def format_date(date):
     if language.startswith('es-'):
         return strftime_localized(date, '%-d de %b. de %Y').lower()
     else:
         return strftime_localized(date, '%b. %-d, %Y')
Ejemplo n.º 54
0
 def _attach_run_mode_enrollment_open_date(self, run_mode):
     run_mode['enrollment_open_date'] = strftime_localized(self.enrollment_start, 'SHORT_DATE')
Ejemplo n.º 55
0
        dtime = datetime(2013, 02, 14, 16, 41, 17)
        self.assertEqual(expected, strftime_localized(dtime, fmt))
        # strftime doesn't like Unicode, so do the work in UTF8.
        self.assertEqual(expected,
                         dtime.strftime(fmt.encode('utf8')).decode('utf8'))

    @ddt.data(
        ("SHORT_DATE", "Feb 14, 2013"),
        ("LONG_DATE", "Thursday, February 14, 2013"),
        ("TIME", "04:41:17 PM"),
        ("DAY_AND_TIME", "Thursday at 4pm"),
        ("%x %X!", "Feb 14, 2013 04:41:17 PM!"),
    )
    def test_shortcuts(self, (fmt, expected)):
        dtime = datetime(2013, 02, 14, 16, 41, 17)
        self.assertEqual(expected, strftime_localized(dtime, fmt))

    @patch('util.date_utils.pgettext',
           fake_pgettext(
               translations={
                   ("abbreviated month name", "Feb"): "XXfebXX",
                   ("month name", "February"): "XXfebruaryXX",
                   ("abbreviated weekday name", "Thu"): "XXthuXX",
                   ("weekday name", "Thursday"): "XXthursdayXX",
                   ("am/pm indicator", "PM"): "XXpmXX",
               }))
    @ddt.data(
        ("SHORT_DATE", "XXfebXX 14, 2013"),
        ("LONG_DATE", "XXthursdayXX, XXfebruaryXX 14, 2013"),
        ("DATE_TIME", "XXfebXX 14, 2013 at 16:41"),
        ("TIME", "04:41:17 XXpmXX"),
Ejemplo n.º 56
0
def check_course_access_with_redirect(course,
                                      user,
                                      action,
                                      check_if_enrolled=False,
                                      check_survey_complete=True,
                                      check_if_authenticated=False):
    """
    Check that the user has the access to perform the specified action
    on the course (CourseDescriptor|CourseOverview).

    check_if_enrolled: If true, additionally verifies that the user is enrolled.
    check_survey_complete: If true, additionally verifies that the user has completed the survey.
    """
    request = get_current_request()
    check_content_start_date_for_masquerade_user(course.id, user, request,
                                                 course.start)

    access_response = check_course_access(course, user, action,
                                          check_if_enrolled,
                                          check_survey_complete,
                                          check_if_authenticated)

    if not access_response:
        # Redirect if StartDateError
        if isinstance(access_response, StartDateError):
            start_date = strftime_localized(course.start, 'SHORT_DATE')
            params = QueryDict(mutable=True)
            params['notlive'] = start_date
            raise CourseAccessRedirect(
                '{dashboard_url}?{params}'.format(
                    dashboard_url=reverse('dashboard'),
                    params=params.urlencode()), access_response)

        # Redirect if AuditExpiredError
        if isinstance(access_response, AuditExpiredError):
            params = QueryDict(mutable=True)
            params[
                'access_response_error'] = access_response.additional_context_user_message
            raise CourseAccessRedirect(
                '{dashboard_url}?{params}'.format(
                    dashboard_url=reverse('dashboard'),
                    params=params.urlencode()), access_response)

        # Redirect if the user must answer a survey before entering the course.
        if isinstance(access_response, MilestoneAccessError):
            raise CourseAccessRedirect(
                '{dashboard_url}'.format(dashboard_url=reverse('dashboard'), ),
                access_response)

        # Redirect if the user is not enrolled and must be to see content
        if isinstance(access_response, EnrollmentRequiredAccessError):
            raise CourseAccessRedirect(
                reverse('about_course', args=[str(course.id)]))

        # Redirect if user must be authenticated to view the content
        if isinstance(access_response, AuthenticationRequiredAccessError):
            raise CourseAccessRedirect(
                reverse('about_course', args=[str(course.id)]))

        # Redirect if the user must answer a survey before entering the course.
        if isinstance(access_response, SurveyRequiredAccessError):
            raise CourseAccessRedirect(
                reverse('course_survey', args=[str(course.id)]))

        # Deliberately return a non-specific error message to avoid
        # leaking info about access control settings
        raise CoursewareAccessException(access_response)
Ejemplo n.º 57
0
 def test_recursion_protection(self, fmt_expected):
     (fmt, expected) = fmt_expected
     dtime = datetime(2013, 2, 14, 16, 41, 17)
     self.assertEqual(expected, strftime_localized(dtime, fmt))
Ejemplo n.º 58
0
 def test_invalid_format_strings(self, fmt):
     dtime = datetime(2013, 02, 14, 16, 41, 17)
     with self.assertRaises(ValueError):
         strftime_localized(dtime, fmt)