Exemplo n.º 1
0
def reset_password(request):
    if settings.STUDENT_SIGN_IN_VIEW != "relate-sign_in_by_user_pw":
        raise SuspiciousOperation(
            _("password-based sign-in is not being used"))

    if request.method == 'POST':
        form = ResetPasswordForm(request.POST)
        if form.is_valid():
            from django.contrib.auth.models import User

            email = form.cleaned_data["email"]
            try:
                user = User.objects.get(email__iexact=email)
            except ObjectDoesNotExist:
                user = None

            if user is None:
                messages.add_message(request, messages.ERROR,
                                     _("Email address is not known."))

            from course.models import get_user_status
            ustatus = get_user_status(user)
            ustatus.sign_in_key = make_sign_in_key(user)
            ustatus.save()

            from django.template.loader import render_to_string
            message = render_to_string(
                "course/sign-in-email.txt", {
                    "user":
                    user,
                    "sign_in_uri":
                    request.build_absolute_uri(
                        reverse("relate-reset_password_stage2",
                                args=(
                                    user.id,
                                    ustatus.sign_in_key,
                                ))),
                    "home_uri":
                    request.build_absolute_uri(reverse("relate-home"))
                })
            from django.core.mail import send_mail
            send_mail(string_concat("[", _("RELATE"), "] ",
                                    _("Password reset")),
                      message,
                      settings.ROBOT_EMAIL_FROM,
                      recipient_list=[email])

            messages.add_message(
                request, messages.INFO,
                _("Email sent. Please check your email and click "
                  "the link."))

            return redirect("relate-home")
    else:
        form = ResetPasswordForm()

    return render(request, "generic-form.html", {
        "form_description": _("Reset Password"),
        "form": form
    })
Exemplo n.º 2
0
def get_editor_interaction_mode(page_context):
    if (page_context.flow_session is not None
            and page_context.flow_session.participation is not None):
        from course.models import get_user_status
        ustatus = get_user_status(page_context.flow_session.participation.user)
        return ustatus.editor_mode
    else:
        return "default"
Exemplo n.º 3
0
def reset_password(request):
    if settings.STUDENT_SIGN_IN_VIEW != "relate-sign_in_by_user_pw":
        raise SuspiciousOperation(
                _("password-based sign-in is not being used"))

    if request.method == 'POST':
        form = ResetPasswordForm(request.POST)
        if form.is_valid():

            email = form.cleaned_data["email"]
            try:
                user = get_user_model().objects.get(email__iexact=email)
            except ObjectDoesNotExist:
                user = None

            if user is None:
                messages.add_message(request, messages.ERROR,
                        _("That email address doesn't have an "
                          "associated user account. Are you "
                          "sure you've registered?"))
            else:
                from course.models import get_user_status
                ustatus = get_user_status(user)
                ustatus.sign_in_key = make_sign_in_key(user)
                ustatus.save()

                from django.template.loader import render_to_string
                message = render_to_string("course/sign-in-email.txt", {
                    "user": user,
                    "sign_in_uri": request.build_absolute_uri(
                        reverse(
                            "relate-reset_password_stage2",
                            args=(user.id, ustatus.sign_in_key,))),
                    "home_uri": request.build_absolute_uri(reverse("relate-home"))
                    })
                from django.core.mail import send_mail
                send_mail(
                        string_concat("[", _("RELATE"), "] ",
                                     _("Password reset")),
                        message,
                        settings.ROBOT_EMAIL_FROM,
                        recipient_list=[email])

                messages.add_message(request, messages.INFO,
                        _("Email sent. Please check your email and click "
                        "the link."))

                return redirect("relate-home")
    else:
        form = ResetPasswordForm()

    return render(request, "generic-form.html", {
        "form_description":
            _("Password reset on %(site_name)s")
            % {"site_name": _("RELATE")},
        "form": form
        })
Exemplo n.º 4
0
def view_markup_sandbox(pctx):
    if pctx.role not in [
            participation_role.instructor,
            participation_role.teaching_assistant
    ]:
        raise PermissionDenied(
            ugettext("must be instructor or TA to access sandbox"))

    request = pctx.request
    preview_text = ""

    from course.models import get_user_status
    ustatus = get_user_status(request.user)

    def make_form(data=None):
        help_text = (ugettext("Enter <a href=\"http://documen.tician.de/"
                              "relate/content.html#relate-markup\">"
                              "RELATE markup</a>."))
        return SandboxForm(None, "markdown", ustatus.editor_mode, help_text,
                           data)

    if request.method == "POST":
        form = make_form(request.POST)

        if form.is_valid():
            from course.content import markup_to_html
            try:
                preview_text = markup_to_html(pctx.course, pctx.repo,
                                              pctx.course_commit_sha,
                                              form.cleaned_data["content"])
            except:
                import sys
                tp, e, _ = sys.exc_info()

                messages.add_message(
                    pctx.request, messages.ERROR,
                    ugettext("Markup failed to render") + ": " +
                    "%(err_type)s: %(err_str)s" % {
                        "err_type": tp.__name__,
                        "err_str": e
                    })

        form = make_form(request.POST)

    else:
        form = make_form()

    return render_course_page(pctx, "course/sandbox-markup.html", {
        "form": form,
        "preview_text": preview_text,
    })
Exemplo n.º 5
0
def view_markup_sandbox(pctx):
    if pctx.role not in [
            participation_role.instructor,
            participation_role.teaching_assistant]:
        raise PermissionDenied(
                ugettext("must be instructor or TA to access sandbox"))

    request = pctx.request
    preview_text = ""

    from course.models import get_user_status
    ustatus = get_user_status(request.user)

    def make_form(data=None):
        help_text = (ugettext("Enter <a href=\"http://documen.tician.de/"
                "relate/content.html#relate-markup\">"
                "RELATE markup</a>."))
        return SandboxForm(
                None, "markdown", ustatus.editor_mode,
                help_text,
                data)

    if request.method == "POST":
        form = make_form(request.POST)

        if form.is_valid():
            from course.content import markup_to_html
            try:
                preview_text = markup_to_html(
                        pctx.course, pctx.repo, pctx.course_commit_sha,
                        form.cleaned_data["content"])
            except:
                import sys
                tp, e, _ = sys.exc_info()

                messages.add_message(pctx.request, messages.ERROR,
                        ugettext("Markup failed to render")
                        + ": "
                        + "%(err_type)s: %(err_str)s" % {
                            "err_type": tp.__name__, "err_str": e})

        form = make_form(request.POST)

    else:
        form = make_form()

    return render_course_page(pctx, "course/sandbox-markup.html", {
        "form": form,
        "preview_text": preview_text,
    })
Exemplo n.º 6
0
def user_profile(request):
    if not request.user.is_authenticated():
        raise PermissionDenied()

    from course.models import get_user_status
    ustatus = get_user_status(request.user)

    user_form = None
    user_status_form = None

    if request.method == "POST":
        if "submit_user" in request.POST:
            user_form = UserForm(request.POST, instance=request.user)
            if user_form.is_valid():
                user_form.save()

                messages.add_message(request, messages.INFO,
                        _("Profile data saved."))
                if request.GET.get("first_login"):
                    return redirect("relate-home")

        if "submit_user_status" in request.POST:
            user_status_form = UserStatusForm(
                    request.POST, instance=ustatus)
            if user_status_form.is_valid():
                user_status_form.save()
                messages.add_message(request, messages.INFO,
                        _("Profile data saved."))
                if request.GET.get("first_login"):
                    return redirect("relate-home")

    if user_form is None:
        user_form = UserForm(instance=request.user)
    if user_status_form is None:
        user_status_form = UserStatusForm(instance=ustatus)

    return render(request, "user-profile-form.html", {
        "user_form": user_form,
        "user_status_form": user_status_form,
        })
Exemplo n.º 7
0
def user_profile(request):
    if not request.user.is_authenticated():
        raise PermissionDenied()

    from course.models import get_user_status
    ustatus = get_user_status(request.user)

    user_form = None
    user_status_form = None

    if request.method == "POST":
        if "submit_user" in request.POST:
            user_form = UserForm(request.POST, instance=request.user)
            if user_form.is_valid():
                user_form.save()

                messages.add_message(request, messages.INFO,
                        _("Profile data saved."))
                if request.GET.get("first_login"):
                    return redirect("relate-home")

        if "submit_user_status" in request.POST:
            user_status_form = UserStatusForm(
                    request.POST, instance=ustatus)
            if user_status_form.is_valid():
                user_status_form.save()
                messages.add_message(request, messages.INFO,
                        _("Profile data saved."))
                if request.GET.get("first_login"):
                    return redirect("relate-home")

    if user_form is None:
        user_form = UserForm(instance=request.user)
    if user_status_form is None:
        user_status_form = UserStatusForm(instance=ustatus)

    return render(request, "user-profile-form.html", {
        "user_form": user_form,
        "user_status_form": user_status_form,
        })
Exemplo n.º 8
0
def enroll(request, course_identifier):
    course = get_object_or_404(Course, identifier=course_identifier)
    role, participation = get_role_and_participation(request, course)

    if role != participation_role.unenrolled:
        messages.add_message(request, messages.ERROR,
                             _("Already enrolled. Cannot re-renroll."))
        return redirect("relate-course_page", course_identifier)

    if not course.accepts_enrollment:
        messages.add_message(request, messages.ERROR,
                             _("Course is not accepting enrollments."))
        return redirect("relate-course_page", course_identifier)

    if request.method != "POST":
        # This can happen if someone tries to refresh the page, or switches to
        # desktop view on mobile.
        messages.add_message(request, messages.ERROR,
                             _("Can only enroll using POST request"))
        return redirect("relate-course_page", course_identifier)

    user = request.user
    ustatus = get_user_status(user)
    if (course.enrollment_required_email_suffix
            and ustatus.status != user_status.active):
        messages.add_message(
            request, messages.ERROR,
            _("Your email address is not yet confirmed. "
              "Confirm your email to continue."))
        return redirect("relate-course_page", course_identifier)

    preapproval = None
    if request.user.email:
        try:
            preapproval = ParticipationPreapproval.objects.get(
                course=course, email__iexact=request.user.email)
        except ParticipationPreapproval.DoesNotExist:
            pass

    if (preapproval is None and course.enrollment_required_email_suffix and
            not user.email.endswith(course.enrollment_required_email_suffix)):

        messages.add_message(
            request, messages.ERROR,
            _("Enrollment not allowed. Please use your '%s' email to "
              "enroll.") % course.enrollment_required_email_suffix)
        return redirect("relate-course_page", course_identifier)

    def enroll(status, role):
        participations = Participation.objects.filter(course=course, user=user)

        assert participations.count() <= 1
        if participations.count() == 0:
            participation = Participation()
            participation.user = user
            participation.course = course
            participation.role = role
            participation.status = status
            participation.save()
        else:
            (participation, ) = participations
            participation.status = status
            participation.save()

        return participation

    role = participation_role.student

    if preapproval is not None:
        role = preapproval.role

    if course.enrollment_approval_required and preapproval is None:
        enroll(participation_status.requested, role)

        with translation.override(settings.RELATE_ADMIN_EMAIL_LOCALE):
            from django.template.loader import render_to_string
            message = render_to_string(
                "course/enrollment-request-email.txt", {
                    "user":
                    user,
                    "course":
                    course,
                    "admin_uri":
                    request.build_absolute_uri(
                        reverse("admin:course_participation_changelist") +
                        "?status__exact=requested")
                })

            from django.core.mail import send_mail
            send_mail(string_concat("[%s] ", _("New enrollment request")) %
                      course_identifier,
                      message,
                      settings.ROBOT_EMAIL_FROM,
                      recipient_list=[course.notify_email])

        messages.add_message(
            request, messages.INFO,
            _("Enrollment request sent. You will receive notifcation "
              "by email once your request has been acted upon."))
    else:
        enroll(participation_status.active, role)

        messages.add_message(request, messages.SUCCESS,
                             _("Successfully enrolled."))

    return redirect("relate-course_page", course_identifier)
Exemplo n.º 9
0
def view_page_sandbox(pctx):
    if pctx.role not in [participation_role.instructor, participation_role.teaching_assistant]:
        raise PermissionDenied(ugettext("must be instructor or TA to access sandbox"))

    from course.validation import ValidationError
    from relate.utils import dict_to_struct, Struct
    import yaml

    PAGE_SESSION_KEY = "cf_validated_sandbox_page:" + pctx.course.identifier  # noqa
    ANSWER_DATA_SESSION_KEY = "cf_page_sandbox_answer_data:" + pctx.course.identifier  # noqa

    request = pctx.request
    page_source = pctx.request.session.get(PAGE_SESSION_KEY)

    page_errors = None
    page_warnings = None

    is_preview_post = request.method == "POST" and "preview" in request.POST

    from course.models import get_user_status

    ustatus = get_user_status(request.user)

    def make_form(data=None):
        return SandboxForm(
            page_source, "yaml", ustatus.editor_mode, ugettext("Enter YAML markup for a flow page."), data
        )

    if is_preview_post:
        edit_form = make_form(pctx.request.POST)

        if edit_form.is_valid():
            try:
                new_page_source = edit_form.cleaned_data["content"]
                page_desc = dict_to_struct(yaml.load(new_page_source))

                if not isinstance(page_desc, Struct):
                    raise ValidationError(
                        "Provided page source code is not "
                        "a dictionary. Do you need to remove a leading "
                        "list marker ('-') or some stray indentation?"
                    )

                from course.validation import validate_flow_page, ValidationContext

                vctx = ValidationContext(repo=pctx.repo, commit_sha=pctx.course_commit_sha)

                validate_flow_page(vctx, "sandbox", page_desc)

                page_warnings = vctx.warnings

            except:
                import sys

                tp, e, _ = sys.exc_info()

                page_errors = (
                    ugettext("Page failed to load/validate")
                    + ": "
                    + "%(err_type)s: %(err_str)s" % {"err_type": tp.__name__, "err_str": e}
                )

            else:
                # Yay, it did validate.
                request.session[PAGE_SESSION_KEY] = page_source = new_page_source

            del new_page_source

        edit_form = make_form(pctx.request.POST)

    else:
        edit_form = make_form()

    have_valid_page = page_source is not None
    if have_valid_page:
        page_desc = dict_to_struct(yaml.load(page_source))

        from course.content import instantiate_flow_page

        try:
            page = instantiate_flow_page("sandbox", pctx.repo, page_desc, pctx.course_commit_sha)
        except:
            import sys

            tp, e, _ = sys.exc_info()

            page_errors = (
                ugettext("Page failed to load/validate")
                + ": "
                + "%(err_type)s: %(err_str)s" % {"err_type": tp.__name__, "err_str": e}
            )
            have_valid_page = False

    if have_valid_page:
        page_data = page.make_page_data()

        from course.models import FlowSession
        from course.page import PageContext

        page_context = PageContext(
            course=pctx.course,
            repo=pctx.repo,
            commit_sha=pctx.course_commit_sha,
            # This helps code pages retrieve the editor pref.
            flow_session=FlowSession(course=pctx.course, participation=pctx.participation),
            in_sandbox=True,
        )

        title = page.title(page_context, page_data)
        body = page.body(page_context, page_data)

        # {{{ try to recover answer_data

        answer_data = None

        stored_answer_data_tuple = pctx.request.session.get(ANSWER_DATA_SESSION_KEY)

        # Session storage uses JSON and may turn tuples into lists.
        if isinstance(stored_answer_data_tuple, (list, tuple)) and len(stored_answer_data_tuple) == 3:
            stored_answer_data_page_type, stored_answer_data_page_id, stored_answer_data = stored_answer_data_tuple

            if stored_answer_data_page_type == page_desc.type and stored_answer_data_page_id == page_desc.id:
                answer_data = stored_answer_data

        # }}}

        feedback = None
        page_form_html = None

        if page.expects_answer():
            from course.page.base import PageBehavior

            page_behavior = PageBehavior(show_correctness=True, show_answer=True, may_change_answer=True)

            if request.method == "POST" and not is_preview_post:
                page_form = page.process_form_post(page_context, page_data, request.POST, request.FILES, page_behavior)

                if page_form.is_valid():

                    answer_data = page.answer_data(page_context, page_data, page_form, request.FILES)

                    feedback = page.grade(page_context, page_data, answer_data, grade_data=None)

                    pctx.request.session[ANSWER_DATA_SESSION_KEY] = (page_desc.type, page_desc.id, answer_data)

            else:
                page_form = page.make_form(page_context, page_data, answer_data, page_behavior)

            if page_form is not None:
                page_form.helper.add_input(Submit("submit", ugettext("Submit answer"), accesskey="g"))
                page_form_html = page.form_to_html(pctx.request, page_context, page_form, answer_data)

        correct_answer = page.correct_answer(page_context, page_data, answer_data, grade_data=None)

        return render_course_page(
            pctx,
            "course/sandbox-page.html",
            {
                "edit_form": edit_form,
                "page_errors": page_errors,
                "page_warnings": page_warnings,
                "form": edit_form,  # to placate form.media
                "have_valid_page": True,
                "title": title,
                "body": body,
                "page_form_html": page_form_html,
                "feedback": feedback,
                "correct_answer": correct_answer,
            },
        )

    else:

        return render_course_page(
            pctx,
            "course/sandbox-page.html",
            {
                "edit_form": edit_form,
                "form": edit_form,  # to placate form.media
                "have_valid_page": False,
                "page_errors": page_errors,
                "page_warnings": page_warnings,
            },
        )
Exemplo n.º 10
0
def enroll(request, course_identifier):
    if request.method != "POST":
        raise SuspiciousOperation("can only enroll using POST request")

    course = get_object_or_404(Course, identifier=course_identifier)
    role, participation = get_role_and_participation(request, course)

    if role != participation_role.unenrolled:
        messages.add_message(request, messages.ERROR,
                             "Already enrolled. Cannot re-renroll.")
        return redirect("course.views.course_page", course_identifier)

    user = request.user
    ustatus = get_user_status(user)
    if (course.enrollment_required_email_suffix
            and ustatus.status != user_status.active):
        messages.add_message(
            request, messages.ERROR,
            "Your email address is not yet confirmed. "
            "Confirm your email to continue.")
        return redirect("course.views.course_page", course_identifier)

    if (course.enrollment_required_email_suffix and
            not user.email.endswith(course.enrollment_required_email_suffix)):

        messages.add_message(
            request, messages.ERROR,
            "Enrollment not allowed. Please use your '%s' email to "
            "enroll." % course.enrollment_required_email_suffix)
        return redirect("course.views.course_page", course_identifier)

    def enroll(status, role):
        participations = Participation.objects.filter(course=course, user=user)

        assert participations.count() <= 1
        if participations.count() == 0:
            participation = Participation()
            participation.user = user
            participation.course = course
            participation.role = role
            participation.status = status
            participation.save()
        else:
            (participation, ) = participations
            participation.status = status
            participation.save()

        return participation

    preapproval = None
    if request.user.email:
        try:
            preapproval = ParticipationPreapproval.objects.get(
                course=course, email__iexact=request.user.email)
        except ParticipationPreapproval.DoesNotExist:
            pass

    role = participation_role.student

    if preapproval is not None:
        role = preapproval.role

    if course.enrollment_approval_required and preapproval is None:
        enroll(participation_status.requested, role)

        from django.template.loader import render_to_string
        message = render_to_string(
            "course/enrollment-request-email.txt", {
                "user":
                user,
                "course":
                course,
                "admin_uri":
                request.build_absolute_uri(
                    reverse("admin:course_participation_changelist"))
            })
        from django.core.mail import send_mail
        send_mail("[%s] New enrollment request" % course_identifier,
                  message,
                  settings.ROBOT_EMAIL_FROM,
                  recipient_list=[course.notify_email])

        messages.add_message(
            request, messages.INFO,
            "Enrollment request sent. You will receive notifcation "
            "by email once your request has been acted upon.")
    else:
        enroll(participation_status.active, role)

        messages.add_message(request, messages.SUCCESS,
                             "Successfully enrolled.")

    return redirect("course.views.course_page", course_identifier)
Exemplo n.º 11
0
def enroll(request, course_identifier):
    course = get_object_or_404(Course, identifier=course_identifier)
    role, participation = get_role_and_participation(request, course)

    if role != participation_role.unenrolled:
        messages.add_message(request, messages.ERROR,
                _("Already enrolled. Cannot re-renroll."))
        return redirect("relate-course_page", course_identifier)

    if not course.accepts_enrollment:
        messages.add_message(request, messages.ERROR,
                _("Course is not accepting enrollments."))
        return redirect("relate-course_page", course_identifier)

    if request.method != "POST":
        # This can happen if someone tries to refresh the page, or switches to
        # desktop view on mobile.
        messages.add_message(request, messages.ERROR,
                _("Can only enroll using POST request"))
        return redirect("relate-course_page", course_identifier)

    user = request.user
    ustatus = get_user_status(user)
    if (course.enrollment_required_email_suffix
            and ustatus.status != user_status.active):
        messages.add_message(request, messages.ERROR,
                _("Your email address is not yet confirmed. "
                "Confirm your email to continue."))
        return redirect("relate-course_page", course_identifier)

    preapproval = None
    if request.user.email:
        try:
            preapproval = ParticipationPreapproval.objects.get(
                    course=course, email__iexact=request.user.email)
        except ParticipationPreapproval.DoesNotExist:
            pass

    if (
            preapproval is None
            and course.enrollment_required_email_suffix
            and not user.email.endswith(course.enrollment_required_email_suffix)):

        messages.add_message(request, messages.ERROR,
                _("Enrollment not allowed. Please use your '%s' email to "
                "enroll.") % course.enrollment_required_email_suffix)
        return redirect("relate-course_page", course_identifier)

    def enroll(status, role):
        participations = Participation.objects.filter(course=course, user=user)

        assert participations.count() <= 1
        if participations.count() == 0:
            participation = Participation()
            participation.user = user
            participation.course = course
            participation.role = role
            participation.status = status
            participation.save()
        else:
            (participation,) = participations
            participation.status = status
            participation.save()

        return participation

    role = participation_role.student

    if preapproval is not None:
        role = preapproval.role

    if course.enrollment_approval_required and preapproval is None:
        enroll(participation_status.requested, role)

        with translation.override(settings.RELATE_ADMIN_EMAIL_LOCALE):
            from django.template.loader import render_to_string
            message = render_to_string("course/enrollment-request-email.txt", {
                "user": user,
                "course": course,
                "admin_uri": request.build_absolute_uri(
                        reverse("admin:course_participation_changelist")
                        + "?status__exact=requested")
                })

            from django.core.mail import send_mail
            send_mail(
                    string_concat("[%s] ", _("New enrollment request"))
                    % course_identifier,
                    message,
                    settings.ROBOT_EMAIL_FROM,
                    recipient_list=[course.notify_email])

        messages.add_message(request, messages.INFO,
                _("Enrollment request sent. You will receive notifcation "
                "by email once your request has been acted upon."))
    else:
        enroll(participation_status.active, role)

        messages.add_message(request, messages.SUCCESS,
                _("Successfully enrolled."))

    return redirect("relate-course_page", course_identifier)
Exemplo n.º 12
0
def enroll(request, course_identifier):
    if request.method != "POST":
        raise SuspiciousOperation("can only enroll using POST request")

    course = get_object_or_404(Course, identifier=course_identifier)
    role, participation = get_role_and_participation(request, course)

    if role != participation_role.unenrolled:
        messages.add_message(request, messages.ERROR,
                "Already enrolled. Cannot re-renroll.")
        return redirect("course.views.course_page", course_identifier)

    user = request.user
    ustatus = get_user_status(user)
    if (course.enrollment_required_email_suffix
            and ustatus.status != user_status.active):
        messages.add_message(request, messages.ERROR,
                "Your email address is not yet confirmed. "
                "Confirm your email to continue.")
        return redirect("course.views.course_page", course_identifier)

    if (course.enrollment_required_email_suffix
            and not user.email.endswith(course.enrollment_required_email_suffix)):

        messages.add_message(request, messages.ERROR,
                "Enrollment not allowed. Please use your '%s' email to "
                "enroll." % course.enrollment_required_email_suffix)
        return redirect("course.views.course_page", course_identifier)

    def enroll(status, role):
        participations = Participation.objects.filter(course=course, user=user)

        assert participations.count() <= 1
        if participations.count() == 0:
            participation = Participation()
            participation.user = user
            participation.course = course
            participation.role = role
            participation.status = status
            participation.save()
        else:
            (participation,) = participations
            participation.status = status
            participation.save()

        return participation

    preapproval = None
    if request.user.email:
        try:
            preapproval = ParticipationPreapproval.objects.get(
                    course=course, email__iexact=request.user.email)
        except ParticipationPreapproval.DoesNotExist:
            pass

    role = participation_role.student

    if preapproval is not None:
        role = preapproval.role

    if course.enrollment_approval_required and preapproval is None:
        enroll(participation_status.requested, role)

        from django.template.loader import render_to_string
        message = render_to_string("course/enrollment-request-email.txt", {
            "user": user,
            "course": course,
            "admin_uri": request.build_absolute_uri(
                    reverse("admin:course_participation_changelist"))
            })
        from django.core.mail import send_mail
        send_mail("[%s] New enrollment request" % course_identifier,
                message,
                settings.ROBOT_EMAIL_FROM,
                recipient_list=[course.email])

        messages.add_message(request, messages.INFO,
                "Enrollment request sent. You will receive notifcation "
                "by email once your request has been acted upon.")
    else:
        enroll(participation_status.active, role)

        messages.add_message(request, messages.SUCCESS,
                "Successfully enrolled.")

    return redirect("course.views.course_page", course_identifier)
Exemplo n.º 13
0
def batch_issue_exam_tickets(pctx):
    from course.models import get_user_status
    ustatus = get_user_status(pctx.request.user)

    if pctx.role not in [
            participation_role.instructor,
            ]:
        raise PermissionDenied(
                _("must be instructor or TA to batch-issue tickets"))

    form_text = ""

    request = pctx.request
    if request.method == "POST":
        form = BatchIssueTicketsForm(pctx.course, ustatus.editor_mode, request.POST)

        if form.is_valid():
            exam = form.cleaned_data["exam"]

            from jinja2 import TemplateSyntaxError
            from course.content import markup_to_html
            try:
                with transaction.atomic():
                    if form.cleaned_data["revoke_prior"]:
                        ExamTicket.objects.filter(
                                exam=exam,
                                state__in=(
                                    exam_ticket_states.valid,
                                    exam_ticket_states.used,
                                    )
                                ).update(state=exam_ticket_states.revoked)

                    tickets = []
                    for participation in (
                            Participation.objects.filter(
                                course=pctx.course,
                                status=participation_status.active)
                            .order_by("user__last_name")
                            ):
                        ticket = ExamTicket()
                        ticket.exam = exam
                        ticket.participation = participation
                        ticket.creator = request.user
                        ticket.state = exam_ticket_states.valid
                        ticket.code = gen_ticket_code()
                        ticket.save()

                        tickets.append(ticket)

                    checkin_uri = pctx.request.build_absolute_uri(
                            reverse("relate-check_in_for_exam"))
                    form_text = markup_to_html(
                            pctx.course, pctx.repo, pctx.course_commit_sha,
                            form.cleaned_data["format"], jinja_env={
                                    "tickets": tickets,
                                    "checkin_uri": checkin_uri,
                                    })
            except TemplateSyntaxError as e:
                messages.add_message(request, messages.ERROR,
                    string_concat(
                        _("Template rendering failed"),
                        ": line %(lineno)d: %(err_str)s")
                    % {
                        "lineno": e.lineno,
                        "err_str": e.message.decode("utf-8")})
            except Exception as e:
                messages.add_message(request, messages.ERROR,
                    string_concat(
                        _("Template rendering failed"),
                        ": %(err_type)s: %(err_str)s")
                    % {"err_type": type(e).__name__,
                        "err_str": str(e)})
            else:
                messages.add_message(request, messages.SUCCESS,
                        _("%d tickets issued.") % len(tickets))

    else:
        form = BatchIssueTicketsForm(pctx.course, ustatus.editor_mode)

    return render_course_page(pctx, "course/batch-exam-tickets-form.html", {
        "form": form,
        "form_text": form_text,
        "form_description": ugettext("Batch-Issue Exam Tickets")
        })
Exemplo n.º 14
0
def view_page_sandbox(pctx):
    if pctx.role not in [
            participation_role.instructor,
            participation_role.teaching_assistant]:
        raise PermissionDenied(
                ugettext("must be instructor or TA to access sandbox"))

    from course.validation import ValidationError
    from relate.utils import dict_to_struct, Struct
    import yaml

    PAGE_SESSION_KEY = (  # noqa
            "cf_validated_sandbox_page:" + pctx.course.identifier)
    ANSWER_DATA_SESSION_KEY = (  # noqa
        "cf_page_sandbox_answer_data:" + pctx.course.identifier)

    request = pctx.request
    page_source = pctx.request.session.get(PAGE_SESSION_KEY)

    page_errors = None
    page_warnings = None

    is_preview_post = (request.method == "POST" and "preview" in request.POST)

    from course.models import get_user_status
    ustatus = get_user_status(request.user)

    def make_form(data=None):
        return SandboxForm(
                page_source, "yaml", ustatus.editor_mode,
                ugettext("Enter YAML markup for a flow page."),
                data)

    if is_preview_post:
        edit_form = make_form(pctx.request.POST)

        if edit_form.is_valid():
            try:
                new_page_source = edit_form.cleaned_data["content"]
                page_desc = dict_to_struct(yaml.load(new_page_source))

                if not isinstance(page_desc, Struct):
                    raise ValidationError("Provided page source code is not "
                            "a dictionary. Do you need to remove a leading "
                            "list marker ('-') or some stray indentation?")

                from course.validation import validate_flow_page, ValidationContext
                vctx = ValidationContext(
                        repo=pctx.repo,
                        commit_sha=pctx.course_commit_sha)

                validate_flow_page(vctx, "sandbox", page_desc)

                page_warnings = vctx.warnings

            except:
                import sys
                tp, e, _ = sys.exc_info()

                page_errors = (
                        ugettext("Page failed to load/validate")
                        + ": "
                        + "%(err_type)s: %(err_str)s" % {
                            "err_type": tp.__name__, "err_str": e})

            else:
                # Yay, it did validate.
                request.session[PAGE_SESSION_KEY] = page_source = new_page_source

            del new_page_source

        edit_form = make_form(pctx.request.POST)

    else:
        edit_form = make_form()

    have_valid_page = page_source is not None
    if have_valid_page:
        page_desc = dict_to_struct(yaml.load(page_source))

        from course.content import instantiate_flow_page
        try:
            page = instantiate_flow_page("sandbox", pctx.repo, page_desc,
                    pctx.course_commit_sha)
        except:
            import sys
            tp, e, _ = sys.exc_info()

            page_errors = (
                    ugettext("Page failed to load/validate")
                    + ": "
                    + "%(err_type)s: %(err_str)s" % {
                        "err_type": tp.__name__, "err_str": e})
            have_valid_page = False

    if have_valid_page:
        page_data = page.make_page_data()

        from course.models import FlowSession
        from course.page import PageContext
        page_context = PageContext(
                course=pctx.course,
                repo=pctx.repo,
                commit_sha=pctx.course_commit_sha,

                # This helps code pages retrieve the editor pref.
                flow_session=FlowSession(
                    course=pctx.course,
                    participation=pctx.participation),

                in_sandbox=True)

        title = page.title(page_context, page_data)
        body = page.body(page_context, page_data)

        # {{{ try to recover answer_data

        answer_data = None

        stored_answer_data_tuple = \
                pctx.request.session.get(ANSWER_DATA_SESSION_KEY)

        # Session storage uses JSON and may turn tuples into lists.
        if (isinstance(stored_answer_data_tuple, (list, tuple))
                and len(stored_answer_data_tuple) == 3):
            stored_answer_data_page_type, stored_answer_data_page_id, stored_answer_data = \
                    stored_answer_data_tuple

            if (
                    stored_answer_data_page_type == page_desc.type
                    and
                    stored_answer_data_page_id == page_desc.id):
                answer_data = stored_answer_data

        # }}}

        feedback = None
        page_form_html = None

        if page.expects_answer():
            from course.page.base import PageBehavior
            page_behavior = PageBehavior(
                    show_correctness=True,
                    show_answer=True,
                    may_change_answer=True)

            if request.method == "POST" and not is_preview_post:
                page_form = page.process_form_post(page_context, page_data,
                        request.POST, request.FILES,
                        page_behavior)

                if page_form.is_valid():

                    answer_data = page.answer_data(page_context, page_data,
                            page_form, request.FILES)

                    feedback = page.grade(page_context, page_data, answer_data,
                            grade_data=None)

                    pctx.request.session[ANSWER_DATA_SESSION_KEY] = (
                            page_desc.type, page_desc.id, answer_data)

            else:
                page_form = page.make_form(page_context, page_data,
                        answer_data, page_behavior)

            if page_form is not None:
                page_form.helper.add_input(
                        Submit("submit",
                            ugettext("Submit answer"),
                            accesskey="g"))
                page_form_html = page.form_to_html(
                        pctx.request, page_context, page_form, answer_data)

        correct_answer = page.correct_answer(
                page_context, page_data, answer_data,
                grade_data=None)

        return render_course_page(pctx, "course/sandbox-page.html", {
            "edit_form": edit_form,
            "page_errors": page_errors,
            "page_warnings": page_warnings,
            "form": edit_form,  # to placate form.media
            "have_valid_page": True,
            "title": title,
            "body": body,
            "page_form_html": page_form_html,
            "feedback": feedback,
            "correct_answer": correct_answer,
        })

    else:

        return render_course_page(pctx, "course/sandbox-page.html", {
            "edit_form": edit_form,
            "form": edit_form,  # to placate form.media
            "have_valid_page": False,
            "page_errors": page_errors,
            "page_warnings": page_warnings,
        })
Exemplo n.º 15
0
def batch_issue_exam_tickets(pctx):
    from course.models import get_user_status
    ustatus = get_user_status(pctx.request.user)

    if pctx.role not in [
            participation_role.instructor,
    ]:
        raise PermissionDenied(
            _("must be instructor or TA to batch-issue tickets"))

    form_text = ""

    request = pctx.request
    if request.method == "POST":
        form = BatchIssueTicketsForm(pctx.course, ustatus.editor_mode,
                                     request.POST)

        if form.is_valid():
            exam = form.cleaned_data["exam"]

            from jinja2 import TemplateSyntaxError
            from course.content import markup_to_html
            try:
                with transaction.atomic():
                    if form.cleaned_data["revoke_prior"]:
                        ExamTicket.objects.filter(
                            exam=exam,
                            state__in=(
                                exam_ticket_states.valid,
                                exam_ticket_states.used,
                            )).update(state=exam_ticket_states.revoked)

                    tickets = []
                    for participation in (Participation.objects.filter(
                            course=pctx.course,
                            status=participation_status.active).order_by(
                                "user__last_name")):
                        ticket = ExamTicket()
                        ticket.exam = exam
                        ticket.participation = participation
                        ticket.creator = request.user
                        ticket.state = exam_ticket_states.valid
                        ticket.code = gen_ticket_code()
                        ticket.save()

                        tickets.append(ticket)

                    checkin_uri = pctx.request.build_absolute_uri(
                        reverse("relate-check_in_for_exam"))
                    form_text = markup_to_html(pctx.course,
                                               pctx.repo,
                                               pctx.course_commit_sha,
                                               form.cleaned_data["format"],
                                               jinja_env={
                                                   "tickets": tickets,
                                                   "checkin_uri": checkin_uri,
                                               })
            except TemplateSyntaxError as e:
                messages.add_message(
                    request, messages.ERROR,
                    string_concat(_("Template rendering failed"),
                                  ": line %(lineno)d: %(err_str)s") % {
                                      "lineno": e.lineno,
                                      "err_str": e.message.decode("utf-8")
                                  })
            except Exception as e:
                messages.add_message(
                    request, messages.ERROR,
                    string_concat(_("Template rendering failed"),
                                  ": %(err_type)s: %(err_str)s") % {
                                      "err_type": type(e).__name__,
                                      "err_str": str(e)
                                  })
            else:
                messages.add_message(request, messages.SUCCESS,
                                     _("%d tickets issued.") % len(tickets))

    else:
        form = BatchIssueTicketsForm(pctx.course, ustatus.editor_mode)

    return render_course_page(
        pctx, "course/batch-exam-tickets-form.html", {
            "form": form,
            "form_text": form_text,
            "form_description": ugettext("Batch-Issue Exam Tickets")
        })