Skip to content
Snippets Groups Projects
views.py 76 KiB
Newer Older
"""
Student Views
"""
import logging
import re
import uuid
from collections import defaultdict
from pytz import UTC
Piotr Mitros's avatar
Piotr Mitros committed
from django.contrib.auth import logout, authenticate, login
from django.contrib.auth.models import User, AnonymousUser
Calen Pennington's avatar
Calen Pennington committed
from django.contrib.auth.decorators import login_required
from django.contrib.auth.views import password_reset_confirm
from django.contrib import messages
Piotr Mitros's avatar
Piotr Mitros committed
from django.core.context_processors import csrf
from django.core.mail import send_mail
Brian Wilson's avatar
Brian Wilson committed
from django.core.urlresolvers import reverse
from django.core.validators import validate_email, validate_slug, ValidationError
from django.db import IntegrityError, transaction
from django.http import (HttpResponse, HttpResponseBadRequest, HttpResponseForbidden,
                         Http404)
from django.shortcuts import redirect
from django.utils.translation import ungettext
from django_future.csrf import ensure_csrf_cookie
from django.utils.http import cookie_date, base36_to_int
from django.utils.translation import ugettext as _, get_language
from django.views.decorators.cache import never_cache
from django.views.decorators.http import require_POST, require_GET
from django.db.models.signals import post_save
from django.dispatch import receiver

from django.template.response import TemplateResponse

Diana Huang's avatar
Diana Huang committed
from ratelimitbackend.exceptions import RateLimitException

David Baumgold's avatar
David Baumgold committed
from edxmako.shortcuts import render_to_response, render_to_string
from mako.exceptions import TopLevelLookupException
Piotr Mitros's avatar
Piotr Mitros committed

from course_modes.models import CourseMode
from student.models import (
    Registration, UserProfile, PendingNameChange,
    PendingEmailChange, CourseEnrollment, unique_id_for_user,
    CourseEnrollmentAllowed, UserStanding, LoginFailures,
    create_comments_service_user, PasswordHistory, UserSignupSource
from student.forms import PasswordResetFormNoActive

from verify_student.models import SoftwareSecurePhotoVerification, MidcourseReverificationWindow
Victor Shnayder's avatar
Victor Shnayder committed
from certificates.models import CertificateStatuses, certificate_status_for_student
from dark_lang.models import DarkLangConfig
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore.django import modulestore
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from xmodule.modulestore import ModuleStoreEnum
Piotr Mitros's avatar
Piotr Mitros committed

from collections import namedtuple
from courseware.courses import get_courses, sort_by_announcement
from courseware.access import has_access
from django_comment_common.models import Role

from external_auth.models import ExternalAuthMap
import external_auth.views
from bulk_email.models import Optout, CourseAuthorization
import shoppingcart
from user_api.models import UserPreference
from lang_pref import LANGUAGE_KEY
from dogapi import dog_stats_api
from util.json_request import JsonResponse
from util.bad_request_rate_limiter import BadRequestRateLimiter
from microsite_configuration import microsite
from util.password_policy_validators import (
    validate_password_length, validate_password_complexity,
    validate_password_dictionary
)

from third_party_auth import pipeline, provider
from xmodule.error_module import ErrorDescriptor
log = logging.getLogger("edx.student")
ReverifyInfo = namedtuple('ReverifyInfo', 'course_id course_name course_number date status display')  # pylint: disable=C0103
Piotr Mitros's avatar
Piotr Mitros committed
def csrf_token(context):
    """A csrf token that can be included in a form."""
Piotr Mitros's avatar
Piotr Mitros committed
    csrf_token = context.get('csrf_token', '')
    if csrf_token == 'NOTPROVIDED':
        return ''
    return (u'<div style="display:none"><input type="hidden"'
            ' name="csrfmiddlewaretoken" value="%s" /></div>' % (csrf_token))
Piotr Mitros's avatar
Piotr Mitros committed

# NOTE: This view is not linked to directly--it is called from
# branding/views.py:index(), which is cached for anonymous users.
# This means that it should always return the same thing for anon
# users. (in particular, no switching based on query params allowed)
def index(request, extra_context={}, user=AnonymousUser()):
ichuang's avatar
ichuang committed
    Render the edX main page.

    extra_context is used to allow immediate display of certain modal windows, eg signup,
    as used by external_auth.
    # The course selection work is done in courseware.courses.
    domain = settings.FEATURES.get('FORCE_UNIVERSITY_DOMAIN')  # normally False
Victor Shnayder's avatar
Victor Shnayder committed
    # do explicit check, because domain=None is valid
    if domain is False:
    courses = get_courses(user, domain=domain)
    courses = sort_by_announcement(courses)
    context = {'courses': courses}
Chris Dodge's avatar
Chris Dodge committed

ichuang's avatar
ichuang committed
    context.update(extra_context)
    return render_to_response('index.html', context)
def embargo(_request):
    """
    Render the embargo page.

    Explains to the user why they are not able to access a particular embargoed course.
    Tries to use the themed version, but fall back to the default if not found.
    try:
        if settings.FEATURES["USE_CUSTOM_THEME"]:
            return render_to_response("static_templates/theme-embargo.html")
    except TopLevelLookupException:
        pass
    return render_to_response("static_templates/embargo.html")
def press(request):
    return render_to_response('static_templates/press.html')
def process_survey_link(survey_link, user):
    """
    If {UNIQUE_ID} appears in the link, replace it with a unique id for the user.
    Currently, this is sha1(user.username).  Otherwise, return survey_link.
    """
    return survey_link.format(UNIQUE_ID=unique_id_for_user(user))


def cert_info(user, course):
    """
    Get the certificate info needed to render the dashboard section for the given
    student and course.  Returns a dictionary with keys:

    'status': one of 'generating', 'ready', 'notpassing', 'processing', 'restricted'
    'show_download_url': bool
    'download_url': url, only present if show_download_url is True
    'show_disabled_download_button': bool -- true if state is 'generating'
    'show_survey_button': bool
    'survey_url': url, only if show_survey_button is True
    'grade': if status is not 'processing'
    """
    if not course.may_certify():
        return {}

    return _cert_info(user, course, certificate_status_for_student(user, course.id))

Calen Pennington's avatar
Calen Pennington committed

def reverification_info(course_enrollment_pairs, user, statuses):
Julia Hansbrough's avatar
Julia Hansbrough committed
    """
    Returns reverification-related information for *all* of user's enrollments whose
    reverification status is in status_list

    Args:
        course_enrollment_pairs (list): list of (course, enrollment) tuples
        user (User): the user whose information we want
        statuses (list): a list of reverification statuses we want information for
            example: ["must_reverify", "denied"]

    Returns:
        dictionary of lists: dictionary with one key per status, e.g.
            dict["must_reverify"] = []
            dict["must_reverify"] = [some information]
    """
    reverifications = defaultdict(list)
    for (course, enrollment) in course_enrollment_pairs:
        info = single_course_reverification_info(user, course, enrollment)
Loading full blame...