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 })
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"
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 })
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, })
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, })
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, })
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, })
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)
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, }, )
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)
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)
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)
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") })
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, })
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") })