Exemple #1
0
def reactivation_email_for_user(user):
    try:
        reg = Registration.objects.get(user=user)
    except Registration.DoesNotExist:
        return HttpResponse(
            json.dumps({
                'success': False,
                'error': 'No inactive user with this e-mail exists'
            }))

    d = {'name': user.profile.name, 'key': reg.activation_key}

    subject = render_to_string('emails/activation_email_subject.txt', d)
    subject = ''.join(subject.splitlines())
    message = render_to_string('emails/activation_email.txt', d)

    try:
        res = user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
    except:
        log.warning('Unable to send reactivation email', exc_info=True)
        return HttpResponse(
            json.dumps({
                'success': False,
                'error': 'Unable to send reactivation email'
            }))

    return HttpResponse(json.dumps({'success': True}))
Exemple #2
0
def send_invite_email(request):
    try:
        data = filter_user(request)
        data = data.filter(subscription_status="Imported")
        remain = request.GET.get("remain")
        count = request.GET.get("count")
        wait = data[: int(count)]
        for item in wait:
            reg = Registration.objects.get(user_id=item.user_id)
            d = {
                "name": "%s %s" % (item.first_name, item.last_name),
                "key": reg.activation_key,
                "district": item.cohort.district.name,
            }
            subject = render_to_string("emails/activation_email_subject.txt", d)
            subject = "".join(subject.splitlines())
            message = render_to_string("emails/activation_email.txt", d)
            try:
                item.user.email_user(subject, message, "*****@*****.**")  # settings.default_from_email
            except Exception as e:
                # log.warning('unable to send reactivation email', exc_info=true)
                raise Exception("unable to send reactivation email: %s" % e)
            item.subscription_status = "Unregistered"
            item.invite_date = datetime.datetime.now(UTC)
            item.save()
            db.transaction.commit()
        ret = {"success": True, "sent": len(wait), "remain": data.count()}
    except Exception as e:
        ret = {"success": False, "error": "%s" % e}
    return HttpResponse(json.dumps(ret))
def send_user_notification_callback(sender, **kwargs):
    """
    Callback for notifying user about course creator status change.
    """
    user = kwargs['user']
    updated_state = kwargs['state']

    studio_request_email = settings.MITX_FEATURES.get('STUDIO_REQUEST_EMAIL',
                                                      '')
    context = {'studio_request_email': studio_request_email}

    subject = render_to_string('emails/course_creator_subject.txt', context)
    subject = ''.join(subject.splitlines())
    if updated_state == CourseCreator.GRANTED:
        message_template = 'emails/course_creator_granted.txt'
    elif updated_state == CourseCreator.DENIED:
        message_template = 'emails/course_creator_denied.txt'
    else:
        # changed to unrequested or pending
        message_template = 'emails/course_creator_revoked.txt'
    message = render_to_string(message_template, context)

    try:
        user.email_user(subject, message, studio_request_email)
    except:
        log.warning("Unable to send course creator status e-mail to %s",
                    user.email)
def send_invite_email(request):
    try:
        data,filtered=filter_user(request)
        data=data.filter(subscription_status='Imported')
        remain=request.GET.get('remain')
        count=request.GET.get('count')
        wait=data[:int(count)]
        for item in wait:
            reg = Registration.objects.get(user_id=item.user_id)
            d = {'name': "%s %s" % (item.user.first_name,item.user.last_name), 'key': reg.activation_key,'district': item.district.name}
            subject = render_to_string('emails/activation_email_subject.txt', d)
            subject = ''.join(subject.splitlines())
            message = render_to_string('emails/activation_email.txt', d)
            try:
                send_html_mail(subject, message, settings.SUPPORT_EMAIL, [item.user.email])
            except Exception as e:
                # log.warning('unable to send reactivation email', exc_info=true)
                raise Exception('unable to send reactivation email: %s' % e)
            item.subscription_status='Unregistered'
            item.invite_date=datetime.datetime.now(UTC)
            item.save()
            db.transaction.commit()
        ret={"success":True,"sent":len(wait),"remain":data.count()}
    except Exception as e:
       ret={"success":False,"error":"%s" % e}
    return HttpResponse(json.dumps(ret))
Exemple #5
0
def update_creator_group_callback(sender, **kwargs):
    """
    Callback for when the model's creator status has changed.
    """
    user = kwargs['user']
    updated_state = kwargs['state']
    update_course_creator_group(kwargs['caller'], user, updated_state == CourseCreator.GRANTED)

    studio_request_email = settings.MITX_FEATURES.get('STUDIO_REQUEST_EMAIL','')
    context = {'studio_request_email': studio_request_email}

    subject = render_to_string('emails/course_creator_subject.txt', context)
    subject = ''.join(subject.splitlines())
    if updated_state == CourseCreator.GRANTED:
        message_template = 'emails/course_creator_granted.txt'
    elif updated_state == CourseCreator.DENIED:
        message_template = 'emails/course_creator_denied.txt'
    else:
        # changed to unrequested or pending
        message_template = 'emails/course_creator_revoked.txt'
    message = render_to_string(message_template, context)

    try:
        user.email_user(subject, message, studio_request_email)
    except:
        log.warning("Unable to send course creator status e-mail to %s", user.email)
Exemple #6
0
def confirm_email_change(request, key):
    ''' User requested a new e-mail. This is called when the activation
    link is clicked. We confirm with the old e-mail, and update
    '''
    try:
        try:
            pec = PendingEmailChange.objects.get(activation_key=key)
        except PendingEmailChange.DoesNotExist:
            transaction.rollback()
            return render_to_response("invalid_email_key.html", {})

        user = pec.user
        address_context = {
            'old_email': user.email,
            'new_email': pec.new_email
        }

        if len(User.objects.filter(email=pec.new_email)) != 0:
            transaction.rollback()
            return render_to_response("email_exists.html", {})

        subject = render_to_string('emails/email_change_subject.txt', address_context)
        subject = ''.join(subject.splitlines())
        message = render_to_string('emails/confirm_email_change.txt', address_context)
        up = UserProfile.objects.get(user=user)
        meta = up.get_meta()
        if 'old_emails' not in meta:
            meta['old_emails'] = []
        meta['old_emails'].append([user.email, datetime.datetime.now().isoformat()])
        up.set_meta(meta)
        up.save()
        # Send it to the old email...
        try:
            user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
        except Exception:
            transaction.rollback()
            log.warning('Unable to send confirmation email to old address', exc_info=True)
            return render_to_response("email_change_failed.html", {'email': user.email})

        user.email = pec.new_email
        user.save()
        pec.delete()
        # And send it to the new email...
        try:
            user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
        except Exception:
            transaction.rollback()
            log.warning('Unable to send confirmation email to new address', exc_info=True)
            return render_to_response("email_change_failed.html", {'email': pec.new_email})

        transaction.commit()
        return render_to_response("email_change_successful.html", address_context)
    except Exception:
        # If we get an unexpected exception, be sure to rollback the transaction
        transaction.rollback()
        raise
def confirm_email_change(request, key):
    ''' User requested a new e-mail. This is called when the activation
    link is clicked. We confirm with the old e-mail, and update
    '''
    try:
        try:
            pec = PendingEmailChange.objects.get(activation_key=key)
        except PendingEmailChange.DoesNotExist:
            transaction.rollback()
            return render_to_response("invalid_email_key.html", {})

        user = pec.user
        address_context = {
            'old_email': user.email,
            'new_email': pec.new_email
        }

        if len(User.objects.filter(email=pec.new_email)) != 0:
            transaction.rollback()
            return render_to_response("email_exists.html", {})

        subject = render_to_string('emails/email_change_subject.txt', address_context)
        subject = ''.join(subject.splitlines())
        message = render_to_string('emails/confirm_email_change.txt', address_context)
        up = UserProfile.objects.get(user=user)
        meta = up.get_meta()
        if 'old_emails' not in meta:
            meta['old_emails'] = []
        meta['old_emails'].append([user.email, datetime.datetime.now().isoformat()])
        up.set_meta(meta)
        up.save()
        # Send it to the old email...
        try:
            user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
        except Exception:
            transaction.rollback()
            log.warning('Unable to send confirmation email to old address', exc_info=True)
            return render_to_response("email_change_failed.html", {'email': user.email})

        user.email = pec.new_email
        user.save()
        pec.delete()
        # And send it to the new email...
        try:
            user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
        except Exception:
            transaction.rollback()
            log.warning('Unable to send confirmation email to new address', exc_info=True)
            return render_to_response("email_change_failed.html", {'email': pec.new_email})

        transaction.commit()
        return render_to_response("email_change_successful.html", address_context)
    except Exception:
        # If we get an unexpected exception, be sure to rollback the transaction
        transaction.rollback()
        raise
Exemple #8
0
def change_email_request(request):
    ''' AJAX call from the profile page. User wants a new e-mail.
    '''
    ## Make sure it checks for existing e-mail conflicts
    if not request.user.is_authenticated:
        raise Http404

    user = request.user

    if not user.check_password(request.POST['password']):
        return HttpResponse(json.dumps({'success': False,
                                        'error': 'Invalid password'}))

    new_email = request.POST['new_email']
    try:
        validate_email(new_email)
    except ValidationError:
        return HttpResponse(json.dumps({'success': False,
                                        'error': 'Valid e-mail address required.'}))

    if User.objects.filter(email=new_email).count() != 0:
        ## CRITICAL TODO: Handle case sensitivity for e-mails
        return HttpResponse(json.dumps({'success': False,
                                        'error': 'An account with this e-mail already exists.'}))

    pec_list = PendingEmailChange.objects.filter(user=request.user)
    if len(pec_list) == 0:
        pec = PendingEmailChange()
        pec.user = user
    else:
        pec = pec_list[0]

    pec.new_email = request.POST['new_email']
    pec.activation_key = uuid.uuid4().hex
    pec.save()

    if pec.new_email == user.email:
        pec.delete()
        return HttpResponse(json.dumps({'success': False,
                                        'error': 'Old email is the same as the new email.'}))

    d = {'key': pec.activation_key,
         'old_email': user.email,
         'new_email': pec.new_email}

    subject = render_to_string('emails/email_change_subject.txt', d)
    subject = ''.join(subject.splitlines())
    message = render_to_string('emails/email_change.txt', d)

    res = send_mail(
        subject, message, settings.DEFAULT_FROM_EMAIL, [pec.new_email])

    return HttpResponse(json.dumps({'success': True}))
Exemple #9
0
def change_email_request(request):
    ''' AJAX call from the profile page. User wants a new e-mail.
    '''
    ## Make sure it checks for existing e-mail conflicts
    if not request.user.is_authenticated:
        raise Http404

    user = request.user

    if not user.check_password(request.POST['password']):
        return HttpResponse(json.dumps({'success': False,
                                        'error': 'Invalid password'}))

    new_email = request.POST['new_email']
    try:
        validate_email(new_email)
    except ValidationError:
        return HttpResponse(json.dumps({'success': False,
                                        'error': 'Valid e-mail address required.'}))

    if User.objects.filter(email=new_email).count() != 0:
        ## CRITICAL TODO: Handle case sensitivity for e-mails
        return HttpResponse(json.dumps({'success': False,
                                        'error': 'An account with this e-mail already exists.'}))

    pec_list = PendingEmailChange.objects.filter(user=request.user)
    if len(pec_list) == 0:
        pec = PendingEmailChange()
        pec.user = user
    else:
        pec = pec_list[0]

    pec.new_email = request.POST['new_email']
    pec.activation_key = uuid.uuid4().hex
    pec.save()

    if pec.new_email == user.email:
        pec.delete()
        return HttpResponse(json.dumps({'success': False,
                                        'error': 'Old email is the same as the new email.'}))

    d = {'key': pec.activation_key,
         'old_email': user.email,
         'new_email': pec.new_email}

    subject = render_to_string('emails/email_change_subject.txt', d)
    subject = ''.join(subject.splitlines())
    message = render_to_string('emails/email_change.txt', d)

    res = send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, [pec.new_email])

    return HttpResponse(json.dumps({'success': True}))
def wrap_xmodule(template, block, view, frag, context):  # pylint: disable=unused-argument
    """
    Wraps the results of get_html in a standard <section> with identifying
    data so that the appropriate javascript module can be loaded onto it.

    get_html: An XModule.get_html method or an XModuleDescriptor.get_html method
    module: An XModule
    template: A template that takes the variables:
        content: the results of get_html,
        display_name: the display name of the xmodule, if available (None otherwise)
        class_: the module class name
        module_name: the js_module_name of the module
    """

    # If XBlock generated this class, then use the first baseclass
    # as the name (since that's the original, unmixed class)
    class_name = getattr(block, 'unmixed_class', block.__class__).__name__

    template_context = {
        'content': frag.content,
        'display_name': block.display_name,
        'class_': class_name,
        'module_name': block.js_module_name,
    }

    return wrap_fragment(frag, render_to_string(template, template_context))
    def purchase(
        self,
        first="",
        last="",
        street1="",
        street2="",
        city="",
        state="",
        postalcode="",
        country="",
        ccnum="",
        cardtype="",
        processor_reply_dump="",
    ):
        """
        Call to mark this order as purchased.  Iterates through its OrderItems and calls
        their purchased_callback

        `first` - first name of person billed (e.g. John)
        `last` - last name of person billed (e.g. Smith)
        `street1` - first line of a street address of the billing address (e.g. 11 Cambridge Center)
        `street2` - second line of a street address of the billing address (e.g. Suite 101)
        `city` - city of the billing address (e.g. Cambridge)
        `state` - code of the state, province, or territory of the billing address (e.g. MA)
        `postalcode` - postal code of the billing address (e.g. 02142)
        `country` - country code of the billing address (e.g. US)
        `ccnum` - last 4 digits of the credit card number of the credit card billed (e.g. 1111)
        `cardtype` - 3-digit code representing the card type used (e.g. 001)
        `processor_reply_dump` - all the parameters returned by the processor

        """
        self.status = "purchased"
        self.purchase_time = datetime.now(pytz.utc)
        self.bill_to_first = first
        self.bill_to_last = last
        self.bill_to_city = city
        self.bill_to_state = state
        self.bill_to_country = country
        self.bill_to_postalcode = postalcode
        if settings.MITX_FEATURES["STORE_BILLING_INFO"]:
            self.bill_to_street1 = street1
            self.bill_to_street2 = street2
            self.bill_to_ccnum = ccnum
            self.bill_to_cardtype = cardtype
            self.processor_reply_dump = processor_reply_dump
        # save these changes on the order, then we can tell when we are in an
        # inconsistent state
        self.save()
        # this should return all of the objects with the correct types of the
        # subclasses
        orderitems = OrderItem.objects.filter(order=self).select_subclasses()
        for item in orderitems:
            item.purchase_item()
        # send confirmation e-mail
        subject = _("Order Payment Confirmation")
        message = render_to_string("emails/order_confirmation_email.txt", {"order": self, "order_items": orderitems})
        try:
            send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, [self.user.email])
        except smtplib.SMTPException:
            log.error("Failed sending confirmation e-mail for order %d", self.id)
Exemple #12
0
def render_notifications(request, course, notifications):
    context = {
        'notifications': notifications,
        'get_discussion_title': partial(get_discussion_title, request=request, course=course),
        'course': course,
    }
    return render_to_string('courseware/notifications.html', context)
Exemple #13
0
def password_reset(request):
    ''' Attempts to send a password reset e-mail. '''
    if request.method != "POST":
        raise Http404

    # By default, Django doesn't allow Users with is_active = False to reset their passwords,
    # but this bites people who signed up a long time ago, never activated, and forgot their
    # password. So for their sake, we'll auto-activate a user for whom password_reset is called.
    try:
        user = User.objects.get(email=request.POST['email'])
        user.is_active = True
        user.save()
    except:
        log.exception("Tried to auto-activate user to enable password reset, but failed.")

    form = PasswordResetForm(request.POST)
    if form.is_valid():
        form.save(use_https=request.is_secure(),
                  from_email=settings.DEFAULT_FROM_EMAIL,
                  request=request,
                  domain_override=request.get_host())
        return HttpResponse(json.dumps({'success': True,
                                        'value': render_to_string('registration/password_reset_done.html', {})}))
    else:
        return HttpResponse(json.dumps({'success': False,
                                        'error': 'Invalid e-mail'}))
Exemple #14
0
def render_notifications(request, course, notifications):
    context = {
        'notifications': notifications,
        'get_discussion_title': partial(get_discussion_title, request=request, course=course),
        'course': course,
    }
    return render_to_string('courseware/notifications.html', context)
Exemple #15
0
def password_reset(request):
    ''' Attempts to send a password reset e-mail. '''
    if request.method != "POST":
        raise Http404

    # By default, Django doesn't allow Users with is_active = False to reset their passwords,
    # but this bites people who signed up a long time ago, never activated, and forgot their
    # password. So for their sake, we'll auto-activate a user for whom password_reset is called.
    try:
        user = User.objects.get(email=request.POST['email'])
        user.is_active = True
        user.save()
    except:
        log.exception("Tried to auto-activate user to enable password reset, but failed.")

    form = PasswordResetForm(request.POST)
    if form.is_valid():
        form.save(use_https=request.is_secure(),
                  from_email=settings.DEFAULT_FROM_EMAIL,
                  request=request,
                  domain_override=request.get_host())
        return HttpResponse(json.dumps({'success': True,
                                        'value': render_to_string('registration/password_reset_done.html', {})}))
    else:
        return HttpResponse(json.dumps({'success': False,
                                        'error': 'Invalid e-mail'}))
Exemple #16
0
def update_moderator_status(request, course_id, user_id):
    """
    given a course id and user id, check if the user has moderator
    and send back a user profile
    """
    is_moderator = request.POST.get('is_moderator', '').lower()
    if is_moderator not in ["true", "false"]:
        return JsonError("Must provide is_moderator as boolean value")
    is_moderator = is_moderator == "true"
    user = User.objects.get(id=user_id)
    role = Role.objects.get(course_id=course_id, name="Moderator")
    if is_moderator:
        user.roles.add(role)
    else:
        user.roles.remove(role)
    if request.is_ajax():
        course = get_course_with_access(request.user, course_id, 'load')
        discussion_user = cc.User(id=user_id, course_id=course_id)
        context = {
            'course': course,
            'course_id': course_id,
            'user': request.user,
            'django_user': user,
            'profiled_user': discussion_user.to_dict(),
        }
        return JsonResponse({
            'html': render_to_string('discussion/ajax_user_profile.html', context)
        })
    else:
        return JsonResponse({})
def hint_manager(request, course_id):
    try:
        get_course_with_access(request.user, course_id, 'staff', depth=None)
    except Http404:
        out = 'Sorry, but students are not allowed to access the hint manager!'
        return HttpResponse(out)
    if request.method == 'GET':
        out = get_hints(request, course_id, 'mod_queue')
        return render_to_response('courseware/hint_manager.html', out)
    field = request.POST['field']
    if not (field == 'mod_queue' or field == 'hints'):
        # Invalid field.  (Don't let users continue - they may overwrite other db's)
        out = 'Error in hint manager - an invalid field was accessed.'
        return HttpResponse(out)

    if request.POST['op'] == 'delete hints':
        delete_hints(request, course_id, field)
    if request.POST['op'] == 'switch fields':
        pass
    if request.POST['op'] == 'change votes':
        change_votes(request, course_id, field)
    if request.POST['op'] == 'add hint':
        add_hint(request, course_id, field)
    if request.POST['op'] == 'approve':
        approve(request, course_id, field)
    rendered_html = render_to_string('courseware/hint_manager_inner.html', get_hints(request, course_id, field))
    return HttpResponse(json.dumps({'success': True, 'contents': rendered_html}))
Exemple #18
0
def render_accordion(request, course, chapter, section, model_data_cache):
    """
    Draws navigation bar. Takes current position in accordion as
    parameter.

    If chapter and section are '' or None, renders a default accordion.

    course, chapter, and section are the url_names.

    Returns the html string
    """

    # grab the table of contents
    user = User.objects.prefetch_related("groups").get(id=request.user.id)
    request.user = user  # keep just one instance of User
    toc = toc_for_course(user, request, course, chapter, section, model_data_cache)

    context = dict(
        [
            ("toc", toc),
            ("course_id", course.id),
            ("csrf", csrf(request)["csrf_token"]),
            ("show_timezone", course.show_timezone),
        ]
        + template_imports.items()
    )
    return render_to_string("courseware/accordion.html", context)
def render_notifications(request, course, notifications):
    context = {
        "notifications": notifications,
        "get_discussion_title": partial(get_discussion_title, request=request, course=course),
        "course": course,
    }
    return render_to_string("courseware/notifications.html", context)
def contact_us_modal_submit(request):
    ret = {"success":True}
    
    if request.POST.get("send_by_js") != 'true':
        ret['success'] = False
        return HttpResponse(json.dumps(ret))

    fullname = request.POST.get("fullname_modal")
    email = request.POST.get("email_modal")
    state = request.POST.get("state_modal")
    district = request.POST.get("district_modal")
    
    from django.core.mail import send_mail
    from mitxmako.shortcuts import render_to_response, render_to_string
    from smtplib import SMTPException
    from mail import send_html_mail

    d = {"email":email, "fullname":fullname, "state":state, "district":district}
    subject = "PepperPd Contact Us From " + request.META['HTTP_HOST']
    body = render_to_string('emails/contact_us_modal_body.txt', d)

    # todo: catch SMTPAuthenticationError and SMTPException

    send_html_mail(subject, body, settings.SUPPORT_EMAIL, [
        settings.SUPPORT_EMAIL,
        "*****@*****.**",  
        "*****@*****.**",
        "*****@*****.**", 
        "*****@*****.**",
        "*****@*****.**"
        ])

    return HttpResponse(json.dumps(ret))
Exemple #21
0
def hint_manager(request, course_id):
    try:
        get_course_with_access(request.user, course_id, 'staff', depth=None)
    except Http404:
        out = 'Sorry, but students are not allowed to access the hint manager!'
        return HttpResponse(out)
    if request.method == 'GET':
        out = get_hints(request, course_id, 'mod_queue')
        return render_to_response('courseware/hint_manager.html', out)
    field = request.POST['field']
    if not (field == 'mod_queue' or field == 'hints'):
        # Invalid field.  (Don't let users continue - they may overwrite other db's)
        out = 'Error in hint manager - an invalid field was accessed.'
        return HttpResponse(out)

    if request.POST['op'] == 'delete hints':
        delete_hints(request, course_id, field)
    if request.POST['op'] == 'switch fields':
        pass
    if request.POST['op'] == 'change votes':
        change_votes(request, course_id, field)
    if request.POST['op'] == 'add hint':
        add_hint(request, course_id, field)
    if request.POST['op'] == 'approve':
        approve(request, course_id, field)
    rendered_html = render_to_string('courseware/hint_manager_inner.html',
                                     get_hints(request, course_id, field))
    return HttpResponse(
        json.dumps({
            'success': True,
            'contents': rendered_html
        }))
Exemple #22
0
def wrap_xmodule(template, block, view, frag, context):  # pylint: disable=unused-argument
    """
    Wraps the results of get_html in a standard <section> with identifying
    data so that the appropriate javascript module can be loaded onto it.

    get_html: An XModule.get_html method or an XModuleDescriptor.get_html method
    module: An XModule
    template: A template that takes the variables:
        content: the results of get_html,
        display_name: the display name of the xmodule, if available (None otherwise)
        class_: the module class name
        module_name: the js_module_name of the module
    """

    # If XBlock generated this class, then use the first baseclass
    # as the name (since that's the original, unmixed class)
    class_name = getattr(block, 'unmixed_class', block.__class__).__name__

    template_context = {
        'content': frag.content,
        'display_name': block.display_name,
        'class_': class_name,
        'module_name': block.js_module_name,
    }

    return wrap_fragment(frag, render_to_string(template, template_context))
    def _get_html():

        if type(module) in [SequenceModule, VerticalModule]:  # TODO: make this more general, eg use an XModule attribute instead
            return get_html()

        module_id = module.id
        if module.descriptor.has_score:
            histogram = grade_histogram(module_id)
            render_histogram = len(histogram) > 0
        else:
            histogram = None
            render_histogram = False

        if settings.MITX_FEATURES.get('ENABLE_LMS_MIGRATION'):
            [filepath, filename] = getattr(module.descriptor, 'xml_attributes', {}).get('filename', ['', None])
            osfs = module.system.filestore
            if filename is not None and osfs.exists(filename):
                # if original, unmangled filename exists then use it (github
                # doesn't like symlinks)
                filepath = filename
            data_dir = osfs.root_path.rsplit('/')[-1]
            giturl = getattr(module.lms, 'giturl', '') or 'https://github.com/MITx'
            edit_link = "%s/%s/tree/master/%s" % (giturl, data_dir, filepath)
        else:
            edit_link = False
            # Need to define all the variables that are about to be used
            giturl = ""
            data_dir = ""

        source_file = module.lms.source_file  # source used to generate the problem XML, eg latex or word

        # useful to indicate to staff if problem has been released or not
        # TODO (ichuang): use _has_access_descriptor.can_load in lms.courseware.access, instead of now>mstart comparison here
        now = datetime.datetime.now(UTC())
        is_released = "unknown"
        mstart = module.descriptor.lms.start

        if mstart is not None:
            is_released = "<font color='red'>Yes!</font>" if (now > mstart) else "<font color='green'>Not yet</font>"

        staff_context = {'fields': [(field.name, getattr(module, field.name)) for field in module.fields],
                         'lms_fields': [(field.name, getattr(module.lms, field.name)) for field in module.lms.fields],
                         'xml_attributes' : getattr(module.descriptor, 'xml_attributes', {}),
                         'location': module.location,
                         'xqa_key': module.lms.xqa_key,
                         'source_file': source_file,
                         'source_url': '%s/%s/tree/master/%s' % (giturl, data_dir, source_file),
                         'category': str(module.__class__.__name__),
                         # Template uses element_id in js function names, so can't allow dashes
                         'element_id': module.location.html_id().replace('-', '_'),
                         'edit_link': edit_link,
                         'user': user,
                         'xqa_server': settings.MITX_FEATURES.get('USE_XQA_SERVER', 'http://*****:*****@content-qa.mitx.mit.edu/xqa'),
                         'histogram': json.dumps(histogram),
                         'render_histogram': render_histogram,
                         'module_content': get_html(),
                         'is_released': is_released,
                         }
        return render_to_string("staff_problem_info.html", staff_context)
def render_purchase_form_html(cart):
    """
    Renders the HTML of the hidden POST form that must be used to initiate a purchase with CyberSource
    """
    return render_to_string('shoppingcart/cybersource_form.html', {
        'action': get_purchase_endpoint(),
        'params': get_signed_purchase_params(cart),
    })
Exemple #25
0
def reactivation_email_for_user(user):
    reg = Registration.objects.get(user=user)

    d = {'name': user.profile.name,
         'key': reg.activation_key}

    subject = render_to_string('emails/activation_email_subject.txt', d)
    subject = ''.join(subject.splitlines())
    message = render_to_string('emails/activation_email.txt', d)

    try:
        res = user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
    except:
        log.warning('Unable to send reactivation email', exc_info=True)
        return HttpResponse(json.dumps({'success': False, 'error': 'Unable to send reactivation email'}))

    return HttpResponse(json.dumps({'success': True}))
Exemple #26
0
def render_js(package, path):
    template_name = package.template_name or "mako/js.html"
    context = package.extra_context
    context.update({
        'type': guess_type(path, 'text/javascript'),
        'url': try_staticfiles_lookup(path)
    })
    return render_to_string(template_name, context)
Exemple #27
0
def render_js(package, path):
    template_name = package.template_name or "mako/js.html"
    context = package.extra_context
    context.update({
        'type': guess_type(path, 'text/javascript'),
        'url': try_staticfiles_lookup(path)
    })
    return render_to_string(template_name, context)
Exemple #28
0
def dashboard(request):
    user = request.user
    enrollments = CourseEnrollment.objects.filter(user=user)

    # Build our courses list for the user, but ignore any courses that no longer
    # exist (because the course IDs have changed). Still, we don't delete those
    # enrollments, because it could have been a data push snafu.
    courses = []
    for enrollment in enrollments:
        try:
            courses.append(course_from_id(enrollment.course_id))
        except ItemNotFoundError:
            log.error("User {0} enrolled in non-existent course {1}".format(
                user.username, enrollment.course_id))

    message = ""
    if not user.is_active:
        message = render_to_string('registration/activate_account_notice.html',
                                   {'email': user.email})

    # Global staff can see what courses errored on their dashboard
    staff_access = False
    errored_courses = {}
    if has_access(user, 'global', 'staff'):
        # Show any courses that errored on load
        staff_access = True
        errored_courses = modulestore().get_errored_courses()

    show_courseware_links_for = frozenset(
        course.id for course in courses
        if has_access(request.user, course, 'load'))

    cert_statuses = {
        course.id: cert_info(request.user, course)
        for course in courses
    }

    exam_registrations = {
        course.id: exam_registration_info(request.user, course)
        for course in courses
    }

    # Get the 3 most recent news
    top_news = _get_news(top=3) if not settings.MITX_FEATURES.get(
        'ENABLE_MKTG_SITE', False) else None

    context = {
        'courses': courses,
        'message': message,
        'staff_access': staff_access,
        'errored_courses': errored_courses,
        'show_courseware_links_for': show_courseware_links_for,
        'cert_statuses': cert_statuses,
        'news': top_news,
        'exam_registrations': exam_registrations,
    }

    return render_to_response('dashboard.html', context)
def render_purchase_form_html(cart):
    """
    Renders the HTML of the hidden POST form that must be used to initiate a purchase with CyberSource
    """
    return render_to_string(
        'shoppingcart/cybersource_form.html', {
            'action': get_purchase_endpoint(),
            'params': get_signed_purchase_params(cart),
        })
    def _get_html():
        context.update({
            'content': get_html(),
            'display_name': module.display_name,
            'class_': class_name,
            'module_name': module.js_module_name
        })

        return render_to_string(template, context)
Exemple #31
0
    def purchase(self, first='', last='', street1='', street2='', city='', state='', postalcode='',
                 country='', ccnum='', cardtype='', processor_reply_dump=''):
        """
        Call to mark this order as purchased.  Iterates through its OrderItems and calls
        their purchased_callback

        `first` - first name of person billed (e.g. John)
        `last` - last name of person billed (e.g. Smith)
        `street1` - first line of a street address of the billing address (e.g. 11 Cambridge Center)
        `street2` - second line of a street address of the billing address (e.g. Suite 101)
        `city` - city of the billing address (e.g. Cambridge)
        `state` - code of the state, province, or territory of the billing address (e.g. MA)
        `postalcode` - postal code of the billing address (e.g. 02142)
        `country` - country code of the billing address (e.g. US)
        `ccnum` - last 4 digits of the credit card number of the credit card billed (e.g. 1111)
        `cardtype` - 3-digit code representing the card type used (e.g. 001)
        `processor_reply_dump` - all the parameters returned by the processor

        """
        if self.status == 'purchased':
            return
        self.status = 'purchased'
        self.purchase_time = datetime.now(pytz.utc)
        self.bill_to_first = first
        self.bill_to_last = last
        self.bill_to_city = city
        self.bill_to_state = state
        self.bill_to_country = country
        self.bill_to_postalcode = postalcode
        if settings.MITX_FEATURES['STORE_BILLING_INFO']:
            self.bill_to_street1 = street1
            self.bill_to_street2 = street2
            self.bill_to_ccnum = ccnum
            self.bill_to_cardtype = cardtype
            self.processor_reply_dump = processor_reply_dump

        # save these changes on the order, then we can tell when we are in an
        # inconsistent state
        self.save()
        # this should return all of the objects with the correct types of the
        # subclasses
        orderitems = OrderItem.objects.filter(order=self).select_subclasses()
        for item in orderitems:
            item.purchase_item()

        # send confirmation e-mail
        subject = _("Order Payment Confirmation")
        message = render_to_string('emails/order_confirmation_email.txt', {
            'order': self,
            'order_items': orderitems,
            'has_billing_info': settings.MITX_FEATURES['STORE_BILLING_INFO']
        })
        try:
            send_mail(subject, message,
                      settings.DEFAULT_FROM_EMAIL, [self.user.email])  # pylint: disable=E1101
        except (smtplib.SMTPException, BotoServerError):  # sadly need to handle diff. mail backends individually
            log.error('Failed sending confirmation e-mail for order %d', self.id)  # pylint: disable=E1101
    def _get_html():
        context.update({
            'content': get_html(),
            'display_name': module.display_name,
            'class_': module.__class__.__name__,
            'module_name': module.js_module_name
        })

        return render_to_string(template, context)
Exemple #33
0
    def purchase(self, first='', last='', street1='', street2='', city='', state='', postalcode='',
                 country='', ccnum='', cardtype='', processor_reply_dump=''):
        """
        Call to mark this order as purchased.  Iterates through its OrderItems and calls
        their purchased_callback

        `first` - first name of person billed (e.g. John)
        `last` - last name of person billed (e.g. Smith)
        `street1` - first line of a street address of the billing address (e.g. 11 Cambridge Center)
        `street2` - second line of a street address of the billing address (e.g. Suite 101)
        `city` - city of the billing address (e.g. Cambridge)
        `state` - code of the state, province, or territory of the billing address (e.g. MA)
        `postalcode` - postal code of the billing address (e.g. 02142)
        `country` - country code of the billing address (e.g. US)
        `ccnum` - last 4 digits of the credit card number of the credit card billed (e.g. 1111)
        `cardtype` - 3-digit code representing the card type used (e.g. 001)
        `processor_reply_dump` - all the parameters returned by the processor

        """
        if self.status == 'purchased':
            return
        self.status = 'purchased'
        self.purchase_time = datetime.now(pytz.utc)
        self.bill_to_first = first
        self.bill_to_last = last
        self.bill_to_city = city
        self.bill_to_state = state
        self.bill_to_country = country
        self.bill_to_postalcode = postalcode
        if settings.MITX_FEATURES['STORE_BILLING_INFO']:
            self.bill_to_street1 = street1
            self.bill_to_street2 = street2
            self.bill_to_ccnum = ccnum
            self.bill_to_cardtype = cardtype
            self.processor_reply_dump = processor_reply_dump

        # save these changes on the order, then we can tell when we are in an
        # inconsistent state
        self.save()
        # this should return all of the objects with the correct types of the
        # subclasses
        orderitems = OrderItem.objects.filter(order=self).select_subclasses()
        for item in orderitems:
            item.purchase_item()

        # send confirmation e-mail
        subject = _("Order Payment Confirmation")
        message = render_to_string('emails/order_confirmation_email.txt', {
            'order': self,
            'order_items': orderitems,
            'has_billing_info': settings.MITX_FEATURES['STORE_BILLING_INFO']
        })
        try:
            send_mail(subject, message,
                      settings.DEFAULT_FROM_EMAIL, [self.user.email])  # pylint: disable=E1101
        except (smtplib.SMTPException, BotoServerError):  # sadly need to handle diff. mail backends individually
            log.error('Failed sending confirmation e-mail for order %d', self.id)  # pylint: disable=E1101
def render_accordion(request, course, chapter, section, model_data_cache):
    """
    Draws navigation bar. Takes current position in accordion as
    parameter.

    If chapter and section are '' or None, renders a default accordion.

    course, chapter, and section are the url_names.

    Returns the html string
    """

    staff_access = has_access(request.user, course, "staff")

    # NOTE: To make sure impersonation by instructor works, use
    # student instead of request.user in the rest of the function.

    # The pre-fetching of groups is done to make auth checks not require an
    # additional DB lookup (this kills the Progress page in particular).
    course_id = course.id
    student_id = None
    if student_id is None or student_id == request.user.id:
        # always allowed to see your own profile
        student = request.user
    else:
        # Requesting access to a different student's profile
        if not staff_access:
            raise Http404
        student = User.objects.get(id=int(student_id))

    student = User.objects.prefetch_related("groups").get(id=student.id)

    model_data_cache = ModelDataCache.cache_for_descriptor_descendents(course_id, student, course, depth=None)

    courseware_summary = grades.progress_summary(student, request, course, model_data_cache)

    print("<-------------")
    print(courseware_summary)
    print("------------->")

    # grab the table of contents
    user = User.objects.prefetch_related("groups").get(id=request.user.id)
    request.user = user  # keep just one instance of User
    toc = toc_for_course(user, request, course, chapter, section, model_data_cache)

    context = dict(
        [
            ("toc", toc),
            ("course_id", course.id),
            ("csrf", csrf(request)["csrf_token"]),
            ("show_timezone", course.show_timezone),
            ("courseware_summary", courseware_summary),
        ]
        + template_imports.items()
    )
    return render_to_string("courseware/accordion.html", context)
def dashboard(request):
    user = request.user
    enrollments = CourseEnrollment.objects.filter(user=user)

    # Build our courses list for the user, but ignore any courses that no longer
    # exist (because the course IDs have changed). Still, we don't delete those
    # enrollments, because it could have been a data push snafu.
    courses = []
    for enrollment in enrollments:
        try:
            courses.append(course_from_id(enrollment.course_id))
        except ItemNotFoundError:
            log.error("User {0} enrolled in non-existent course {1}"
                      .format(user.username, enrollment.course_id))

    message = ""
    if not user.is_active:
        message = render_to_string('registration/activate_account_notice.html', {'email': user.email})

    # Global staff can see what courses errored on their dashboard
    staff_access = False
    errored_courses = {}
    if has_access(user, 'global', 'staff'):
        # Show any courses that errored on load
        staff_access = True
        errored_courses = modulestore().get_errored_courses()

    show_courseware_links_for = frozenset(course.id for course in courses
                                          if has_access(request.user, course, 'load'))

    cert_statuses = {course.id: cert_info(request.user, course) for course in courses}

    exam_registrations = {course.id: exam_registration_info(request.user, course) for course in courses}

    # Get the 3 most recent news
    top_news = _get_news(top=3) if not settings.MITX_FEATURES.get('ENABLE_MKTG_SITE', False) else None
            
    # get info w.r.t ExternalAuthMap
    external_auth_map = None
    try:
        external_auth_map = ExternalAuthMap.objects.get(user=user)
    except ExternalAuthMap.DoesNotExist:
        pass

    context = {'courses': courses,
               'message': message,
               'external_auth_map': external_auth_map,
               'staff_access': staff_access,
               'errored_courses': errored_courses,
               'show_courseware_links_for': show_courseware_links_for,
               'cert_statuses': cert_statuses,
               'news': top_news,
               'exam_registrations': exam_registrations,
               }

    return render_to_response('dashboard.html', context)
Exemple #36
0
def render_css(package, path):
    template_name = package.template_name or "mako/css.html"
    context = package.extra_context

    url = try_staticfiles_lookup(path)
    context.update({
        'type': guess_type(path, 'text/css'),
        'url': url,
    })
    return render_to_string(template_name, context)
Exemple #37
0
def render_css(package, path):
    template_name = package.template_name or "mako/css.html"
    context = package.extra_context

    url = try_staticfiles_lookup(path)
    context.update({
        'type': guess_type(path, 'text/css'),
        'url': url,
    })
    return render_to_string(template_name, context)
Exemple #38
0
def get_preview_html(request, descriptor, idx):
    """
    Returns the HTML returned by the XModule's student_view,
    specified by the descriptor and idx.
    """
    module = load_preview_module(request, str(idx), descriptor)
    try:
        content = module.render("student_view").content
    except Exception as exc:                          # pylint: disable=W0703
        content = render_to_string('html_error.html', {'message': str(exc)})
    return content
Exemple #39
0
def get_preview_html(request, descriptor, idx):
    """
    Returns the HTML returned by the XModule's student_view,
    specified by the descriptor and idx.
    """
    module = load_preview_module(request, str(idx), descriptor)
    try:
        content = module.render("student_view").content
    except Exception as exc:                          # pylint: disable=W0703
        content = render_to_string('html_error.html', {'message': str(exc)})
    return content
    def _get_html():
        context.update(
            {
                "content": get_html(),
                "display_name": module.display_name,
                "class_": module.__class__.__name__,
                "module_name": module.js_module_name,
            }
        )

        return render_to_string(template, context)
Exemple #41
0
def ajax_content_response(request, course_id, content, template_name):
    context = {
        'course_id': course_id,
        'content': content,
    }
    html = render_to_string(template_name, context)
    user_info = cc.User.from_django_user(request.user).to_dict()
    annotated_content_info = utils.get_annotated_content_info(course_id, content, request.user, user_info)
    return JsonResponse({
        'html': html,
        'content': utils.safe_content(content),
        'annotated_content_info': annotated_content_info,
    })
Exemple #42
0
def default_render_failure(request,
                           message,
                           status=403,
                           template_name='extauth_failure.html',
                           exception=None):
    """Render an Openid error page to the user"""

    log.debug("In openid_failure " + message)

    data = render_to_string(template_name,
                            dict(message=message, exception=exception))

    return HttpResponse(data, status=status)
def ajax_content_response(request, course_id, content, template_name):
    context = {
        'course_id': course_id,
        'content': content,
    }
    html = render_to_string(template_name, context)
    user_info = cc.User.from_django_user(request.user).to_dict()
    annotated_content_info = utils.get_annotated_content_info(course_id, content, request.user, user_info)
    return JsonResponse({
        'html': html,
        'content': utils.safe_content(content),
        'annotated_content_info': annotated_content_info,
    })
Exemple #44
0
def send_admin_notification_callback(sender, **kwargs):
    """
    Callback for notifying admin of a user in the 'pending' state.
    """
    user = kwargs['user']

    studio_request_email = settings.MITX_FEATURES.get('STUDIO_REQUEST_EMAIL', '')
    context = {'user_name': user.username, 'user_email': user.email}

    subject = render_to_string('emails/course_creator_admin_subject.txt', context)
    subject = ''.join(subject.splitlines())
    message = render_to_string('emails/course_creator_admin_user_pending.txt', context)

    try:
        send_mail(
            subject,
            message,
            studio_request_email,
            [studio_request_email],
            fail_silently=False
        )
    except SMTPException:
        log.warning("Failure sending 'pending state' e-mail for %s to %s", user.email, studio_request_email)
Exemple #45
0
def send_mail_to_student(student, param_dict):
    """
    Construct the email using templates and then send it.
    `student` is the student's email address (a `str`),

    `param_dict` is a `dict` with keys
    [
        `site_name`: name given to edX instance (a `str`)
        `registration_url`: url for registration (a `str`)
        `course_id`: id of course (a `str`)
        `auto_enroll`: user input option (a `str`)
        `course_url`: url of course (a `str`)
        `email_address`: email of student (a `str`)
        `full_name`: student full name (a `str`)
        `message`: type of email to send and template to use (a `str`)
        `is_shib_course`: (a `boolean`)
    ]

    Returns a boolean indicating whether the email was sent successfully.
    """

    email_template_dict = {'allowed_enroll': ('emails/enroll_email_allowedsubject.txt', 'emails/enroll_email_allowedmessage.txt'),
                           'enrolled_enroll': ('emails/enroll_email_enrolledsubject.txt', 'emails/enroll_email_enrolledmessage.txt'),
                           'allowed_unenroll': ('emails/unenroll_email_subject.txt', 'emails/unenroll_email_allowedmessage.txt'),
                           'enrolled_unenroll': ('emails/unenroll_email_subject.txt', 'emails/unenroll_email_enrolledmessage.txt')}

    subject_template, message_template = email_template_dict.get(param_dict['message'], (None, None))
    if subject_template is not None and message_template is not None:
        subject = render_to_string(subject_template, param_dict)
        message = render_to_string(message_template, param_dict)

        # Remove leading and trailing whitespace from body
        message = message.strip()

        # Email subject *must not* contain newlines
        subject = ''.join(subject.splitlines())
        send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, [student], fail_silently=False)
Exemple #46
0
def wrap_xblock(block, view, frag, context, display_name_only=False):  # pylint: disable=unused-argument
    """
    Wraps the results of rendering an XBlock view in a standard <section> with identifying
    data so that the appropriate javascript module can be loaded onto it.

    :param block: An XBlock (that may be an XModule or XModuleDescriptor)
    :param view: The name of the view that rendered the fragment being wrapped
    :param frag: The :class:`Fragment` to be wrapped
    :param context: The context passed to the view being rendered
    :param display_name_only: If true, don't render the fragment content at all.
        Instead, just render the `display_name` of `block`
    """

    # If any mixins have been applied, then use the unmixed class
    class_name = getattr(block, 'unmixed_class', block.__class__).__name__

    data = {}
    css_classes = ['xblock', 'xblock-' + view]

    if isinstance(block, (XModule, XModuleDescriptor)):
        if view == 'student_view':
            # The block is acting as an XModule
            css_classes.append('xmodule_display')
        elif view == 'studio_view':
            # The block is acting as an XModuleDescriptor
            css_classes.append('xmodule_edit')

        css_classes.append('xmodule_' + class_name)
        data['type'] = block.js_module_name
        shim_xmodule_js(frag)

    if frag.js_init_fn:
        data['init'] = frag.js_init_fn
        data['runtime-version'] = frag.js_init_version
        data['usage-id'] = block.scope_ids.usage_id
        data['block-type'] = block.scope_ids.block_type

    template_context = {
        'content':
        block.display_name if display_name_only else frag.content,
        'classes':
        css_classes,
        'data_attributes':
        ' '.join('data-{}="{}"'.format(key, value)
                 for key, value in data.items()),
    }

    return wrap_fragment(
        frag, render_to_string('xblock_wrapper.html', template_context))
Exemple #47
0
def send_admin_notification_callback(sender, **kwargs):
    """
    Callback for notifying admin of a user in the 'pending' state.
    """
    user = kwargs['user']

    studio_request_email = settings.MITX_FEATURES.get('STUDIO_REQUEST_EMAIL',
                                                      '')
    context = {'user_name': user.username, 'user_email': user.email}

    subject = render_to_string('emails/course_creator_admin_subject.txt',
                               context)
    subject = ''.join(subject.splitlines())
    message = render_to_string('emails/course_creator_admin_user_pending.txt',
                               context)

    try:
        send_mail(subject,
                  message,
                  studio_request_email, [studio_request_email],
                  fail_silently=False)
    except SMTPException:
        log.warning("Failure sending 'pending state' e-mail for %s to %s",
                    user.email, studio_request_email)
def password_reset(request):
    ''' Attempts to send a password reset e-mail. '''
    if request.method != "POST":
        raise Http404

    form = PasswordResetFormNoActive(request.POST)
    if form.is_valid():
        form.save(use_https=request.is_secure(),
                  from_email=settings.DEFAULT_FROM_EMAIL,
                  request=request,
                  domain_override=request.get_host())
        return HttpResponse(json.dumps({'success': True,
                                        'value': render_to_string('registration/password_reset_done.html', {})}))
    else:
        return HttpResponse(json.dumps({'success': False,
                                        'error': 'Invalid e-mail or user'}))
Exemple #49
0
def render_accordion(request, course, chapter, section, model_data_cache):
    """
    Draws navigation bar. Takes current position in accordion as
    parameter.

    If chapter and section are '' or None, renders a default accordion.

    course, chapter, and section are the url_names.

    Returns the html string
    """

    # grab the table of contents
    user = User.objects.prefetch_related("groups").get(id=request.user.id)
    request.user = user  # keep just one instance of User
    toc = toc_for_course(user, request, course, chapter, section,
                         model_data_cache)

    context = dict([('toc', toc), ('course_id', course.id),
                    ('csrf', csrf(request)['csrf_token']),
                    ('show_timezone', course.show_timezone)] +
                   template_imports.items())
    return render_to_string('courseware/accordion.html', context)
    """
    Get the xmodule.position's display item of an xmodule that has a position and
    children.  If xmodule has no position or is out of bounds, return the first child.
    Returns None only if there are no children at all.
    """
    if not hasattr(xmodule, 'position'):
        return None

    if xmodule.position is None:
        pos = 0
    else:
        # position is 1-indexed.
        pos = xmodule.position - 1

    children = xmodule.get_display_items()
    if 0 <= pos < len(children):
        child = children[pos]
    elif len(children) > 0:
        # Something is wrong.  Default to first child
        child = children[0]
    else:
        child = None
    return child
Exemple #50
0
def search_similar_threads(request, course_id, commentable_id):
    """
    given a course id and commentable id, run query given in text get param
    of request
    """
    text = request.GET.get('text', None)
    if text:
        query_params = {
            'text': text,
            'commentable_id': commentable_id,
        }
        threads = cc.search_similar_threads(course_id, recursive=False, query_params=query_params)
    else:
        theads = []
    context = {'threads': map(utils.extend_content, threads)}
    return JsonResponse({
        'html': render_to_string('discussion/_similar_posts.html', context)
    })
Exemple #51
0
def _get_news(top=None):
    "Return the n top news items on settings.RSS_URL"

    feed_data = cache.get("students_index_rss_feed_data")
    if feed_data is None:
        if hasattr(settings, 'RSS_URL'):
            feed_data = urllib.urlopen(settings.RSS_URL).read()
        else:
            feed_data = render_to_string("feed.rss", None)
        cache.set("students_index_rss_feed_data", feed_data,
                  settings.RSS_TIMEOUT)

    feed = feedparser.parse(feed_data)
    entries = feed['entries'][0:top]  # all entries if top is None
    for entry in entries:
        soup = BeautifulSoup(entry.description)
        entry.image = soup.img['src'] if soup.img else None
        entry.summary = soup.getText()

    return entries
Exemple #52
0
def hint_manager(request, course_id):
    """
    The URL landing function for all calls to the hint manager, both POST and GET.
    """
    try:
        get_course_with_access(request.user, course_id, 'staff', depth=None)
    except Http404:
        out = 'Sorry, but students are not allowed to access the hint manager!'
        return HttpResponse(out)
    if request.method == 'GET':
        out = get_hints(request, course_id, 'mod_queue')
        out.update({'error': ''})
        return render_to_response('instructor/hint_manager.html', out)
    field = request.POST['field']
    if not (field == 'mod_queue' or field == 'hints'):
        # Invalid field.  (Don't let users continue - they may overwrite other db's)
        out = 'Error in hint manager - an invalid field was accessed.'
        return HttpResponse(out)

    switch_dict = {
        'delete hints': delete_hints,
        'switch fields':
        lambda *args: None,  # Takes any number of arguments, returns None.
        'change votes': change_votes,
        'add hint': add_hint,
        'approve': approve,
    }

    # Do the operation requested, and collect any error messages.
    error_text = switch_dict[request.POST['op']](request, course_id, field)
    if error_text is None:
        error_text = ''
    render_dict = get_hints(request, course_id, field)
    render_dict.update({'error': error_text})
    rendered_html = render_to_string('instructor/hint_manager_inner.html',
                                     render_dict)
    return HttpResponse(
        json.dumps({
            'success': True,
            'contents': rendered_html
        }))
Exemple #53
0
def get_licenses_by_course(user, courses):
    licenses = get_courses_licenses(user, courses)
    licenses_by_course = defaultdict(list)

    # create missing licenses and group by course_id
    for software, license in licenses.iteritems():
        if license is None:
            licenses[software] = get_or_create_license(user, software)

        course_id = software.course_id
        serial = license.serial if license else None
        licenses_by_course[course_id].append(License(software, serial))

    # render elements
    data_by_course = {}
    for course_id, licenses in licenses_by_course.iteritems():
        context = {'licenses': licenses}
        template = 'licenses/serial_numbers.html'
        data_by_course[course_id] = render_to_string(template, context)

    return data_by_course
def render_purchase_form_html(cart):
    """
    Renders the HTML of the hidden POST form that must be used to initiate a purchase with CyberSource
    """
    purchase_endpoint = settings.CC_PROCESSOR['CyberSource'].get(
        'PURCHASE_ENDPOINT', '')

    total_cost = cart.total_cost
    amount = "{0:0.2f}".format(total_cost)
    cart_items = cart.orderitem_set.all()
    params = OrderedDict()
    params['amount'] = amount
    params['currency'] = cart.currency
    params['orderPage_transactionType'] = 'sale'
    params['orderNumber'] = "{0:d}".format(cart.id)
    signed_param_dict = sign(params)

    return render_to_string('shoppingcart/cybersource_form.html', {
        'action': purchase_endpoint,
        'params': signed_param_dict,
    })
Exemple #55
0
def render_accordion(request, course, chapter, section, model_data_cache):
    """
    Draws navigation bar. Takes current position in accordion as
    parameter.

    If chapter and section are '' or None, renders a default accordion.

    course, chapter, and section are the url_names.

    Returns the html string
    """

    # grab the table of contents
    user = User.objects.prefetch_related("groups").get(id=request.user.id)
    request.user = user	# keep just one instance of User
    toc = toc_for_course(user, request, course, chapter, section, model_data_cache)

    context = dict([('toc', toc),
                    ('course_id', course.id),
                    ('csrf', csrf(request)['csrf_token']),
                    ('show_timezone', course.show_timezone)] + template_imports.items())
    return render_to_string('courseware/accordion.html', context)
Exemple #56
0
def preview_component(request, location):
    "Return the HTML preview of a component"
    # TODO (vshnayder): change name from id to location in coffee+html as well.
    if not has_access(request.user, location):
        return HttpResponseForbidden()

    component = modulestore().get_item(location)
    # Wrap the generated fragment in the xmodule_editor div so that the javascript
    # can bind to it correctly
    component.runtime.wrappers.append(wrap_xblock)

    try:
        content = component.render('studio_view').content
    # catch exceptions indiscriminately, since after this point they escape the
    # dungeon and surface as uneditable, unsaveable, and undeletable
    # component-goblins.
    except Exception as exc:                          # pylint: disable=W0703
        content = render_to_string('html_error.html', {'message': str(exc)})

    return render_to_response('component.html', {
        'preview': get_preview_html(request, component, 0),
        'editor': content
    })
Exemple #57
0
def password_reset(request):
    ''' Attempts to send a password reset e-mail. '''
    if request.method != "POST":
        raise Http404

    form = PasswordResetFormNoActive(request.POST)
    if form.is_valid():
        form.save(use_https=request.is_secure(),
                  from_email=settings.DEFAULT_FROM_EMAIL,
                  request=request,
                  domain_override=request.get_host())
        return HttpResponse(
            json.dumps({
                'success':
                True,
                'value':
                render_to_string('registration/password_reset_done.html', {})
            }))
    else:
        return HttpResponse(
            json.dumps({
                'success': False,
                'error': 'Invalid e-mail or user'
            }))
Exemple #58
0
def index(request, course_id, chapter=None, section=None, position=None):
    """
    Displays courseware accordion and associated content.  If course, chapter,
    and section are all specified, renders the page, or returns an error if they
    are invalid.

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

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

    Arguments:

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

    Returns:

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

    masq = setup_masquerade(request, staff_access)

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

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

        if chapter is None:
            return redirect_to_course_position(course_module)

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

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

        context['show_chat'] = show_chat

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

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

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

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

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

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

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

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

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

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

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

    return result