Beispiel #1
0
def register_public_key_client(request):
    request.session.pop("registered", None)  # remove if exists, to clear caching

    own_device = Device.get_own_device()
    if own_device.is_registered():
        initialize_registration()
        if request.next:
            return HttpResponseRedirect(request.next)
        else:
            return {"already_registered": True}

    client = RegistrationClient()
    if client.test_connection() != "success":
        return {"no_internet": True}

    reg_response = client.register()
    reg_status = reg_response.get("code")
    if reg_status == "registered":
        initialize_registration()
        if request.next:
            return HttpResponseRedirect(request.next)
        else:
            return {"newly_registered": True}
    elif reg_status == "device_already_registered":
        initialize_registration()
        if request.next:
            return HttpResponseRedirect(request.next)
        else:
            return {"already_registered": True}
    elif reg_status == "public_key_unregistered":
        # Callback url used to redirect to the distributed server url
        #   after successful registration on the central server.
        base_registration_url = client.path_to_url(set_query_params(reverse("register_public_key"), {
            "device_key": urllib.quote(own_device.public_key),
        }))
        return {
            "unregistered": True,
            "auto_registration_url": set_query_params(base_registration_url, {"auto": True}),
            "classic_registration_url": set_query_params(base_registration_url, {
                "callback_url": request.build_absolute_uri(reverse("register_public_key")),
            }),
            "central_login_url": "%s://%s/accounts/login" % (settings.SECURESYNC_PROTOCOL, settings.CENTRAL_SERVER_HOST),
        }

    error_msg = reg_response.get("error", "")
    if error_msg:
        return {"error_msg": error_msg}
    return HttpResponse(_("Registration status: ") + reg_status)
Beispiel #2
0
def group_edit(request, facility, group_id):
    group = get_object_or_None(FacilityGroup, id=group_id)
    facility = facility or (group and group.facility)

    if request.method != 'POST':
        form = FacilityGroupForm(facility, instance=group)

    else:
        form = FacilityGroupForm(facility, data=request.POST, instance=group)
        if not form.is_valid():
            messages.error(
                request,
                _("Failed to save the group; please review errors below."))
        else:
            form.save()

            redir_url = request.next or request.GET.get("prev") or reverse(
                "add_facility_student")
            redir_url = set_query_params(redir_url, {
                "facility": facility.pk,
                "group": form.instance.pk
            })
            return HttpResponseRedirect(redir_url)

    return {
        "form": form,
        "group_id": group_id,
        "facility": facility,
        "singlefacility": request.session["facility_count"] == 1,
        "title":
        _("Add a new group") if group_id == 'new' else _("Edit group"),
    }
Beispiel #3
0
def group_edit(request, facility, group_id):
    group = get_object_or_None(FacilityGroup, id=group_id)
    facility = facility or (group and group.facility)

    if request.method != 'POST':
        form = FacilityGroupForm(facility, instance=group)

    else:
        form = FacilityGroupForm(facility, data=request.POST, instance=group)
        if not form.is_valid():
            messages.error(request, _("Failed to save the group; please review errors below."))
        else:
            form.save()

            redir_url = request.next or request.GET.get("prev") or reverse("add_facility_student")
            redir_url = set_query_params(redir_url, {"facility": facility.pk, "group": form.instance.pk})
            return HttpResponseRedirect(redir_url)

    return {
        "form": form,
        "group_id": group_id,
        "facility": facility,
        "singlefacility": request.session["facility_count"] == 1,
        "title": _("Add a new group") if group_id == 'new' else _("Edit group"),
    }
Beispiel #4
0
 def real_decorator_wrapper_fn(request, *args, **kwargs):
     if Device.get_own_device().is_registered():
         return handler(request, *args, **kwargs)
     else:
         messages.warning(request, _("In order to access %(resource_name)s, you must register your device first." % {"resource_name": unicode(resource_name)}))
         return HttpResponseRedirect(
             set_query_params(reverse('register_public_key'), {'next': request.path})
         )
Beispiel #5
0
    def get_registration_url(self, **kwargs):

        if "device_key" not in kwargs:
            kwargs["device_key"] = urllib.quote(
                Device.get_own_device().public_key)

        return self.path_to_url(
            set_query_params(reverse("register_public_key"), kwargs))
Beispiel #6
0
def handler_403(request, *args, **kwargs):
    context = RequestContext(request)

    if request.is_ajax():
        return JsonResponseMessageError(_("You must be logged in with an account authorized to view this page (API)."), status=403)
    else:
        messages.error(request, mark_safe(_("You must be logged in with an account authorized to view this page.")))
        return HttpResponseRedirect(set_query_params(reverse("auth_login"), {"next": request.get_full_path()}))
Beispiel #7
0
def handler_403(request, *args, **kwargs):
    context = RequestContext(request)
    #message = None  # Need to retrieve, but can't figure it out yet.

    if request.is_ajax():
        return JsonResponse({ "error": _("You must be logged in with an account authorized to view this page.") }, status=403)
    else:
        messages.error(request, mark_safe(_("You must be logged in with an account authorized to view this page.")))
        return HttpResponseRedirect(set_query_params(reverse("login"), {"next": request.get_full_path()}))
Beispiel #8
0
def handler_403(request, *args, **kwargs):
    context = RequestContext(request)
    #message = None  # Need to retrieve, but can't figure it out yet.

    if request.is_ajax():
        return JsonResponseMessageError(_("You must be logged in with an account authorized to view this page (API)."), status=403)
    else:
        messages.error(request, mark_safe(_("You must be logged in with an account authorized to view this page.")))
        return HttpResponseRedirect(set_query_params(reverse("login"), {"next": request.get_full_path()}))
Beispiel #9
0
def update_all_distributed(request):
    """
    """
    logging.debug("Getting Khan Academy data.")

    return HttpResponseRedirect(set_query_params(CENTRAL_SERVER_URL + CENTRAL_UPDATE_ALL_PATH, {
        "callback": request.build_absolute_uri(reverse("update_all_distributed_callback")),
        "user_id": request.session["facility_user"].id,
    }))
Beispiel #10
0
def update_all_distributed(request):
    """
    """
    logging.debug("Getting Khan Academy data.")

    return HttpResponseRedirect(set_query_params(CENTRAL_SERVER_URL + CENTRAL_UPDATE_ALL_PATH, {
        "callback": request.build_absolute_uri(reverse("update_all_distributed_callback")),
        "user_id": request.session["facility_user"].id,
    }))
Beispiel #11
0
def login_view(request, *args, **kwargs):
    """
    Force lowercase of the username.

    Since we don't want things to change to the user (if something fails),
    we should try the new way first, then fall back to the old way
    """

    prev = None

    if request.method == "POST":
        users = User.objects.filter(username__iexact=request.POST["username"])
        nusers = users.count()

        # Coerce
        if nusers == 1 and users[0].username != request.POST["username"]:
            request.POST = copy.deepcopy(request.POST)
            request.POST['username'] = request.POST['username'].lower()

        prev = request.POST.get('prev') or request.META.get("HTTP_REFERER")

    prev = prev or request.META.get("HTTP_REFERER")

    # Note: prev used because referer is lost on a login / redirect.
    #   So paste it on the success redirect.
    redirect_url = request.REQUEST.get("next", reverse('org_management'))
    if prev:
        redirect_url = set_query_params(redirect_url, {"prev": prev})

    extra_context = {
        "redirect": {
            "name": REDIRECT_FIELD_NAME,
            "url": redirect_url,
        },
        "auth_password_reset_url":
        reverse("auth_password_reset"),
        "registration_register_url":
        reverse("registration_register")
        if not request.next else set_query_params(
            reverse("registration_register"), {"next": request.next}),
    }
    kwargs["extra_context"] = extra_context

    return auth_views.login(request, *args, **kwargs)
def set_language_data(request):
    """
    Process requests to set language, redirect to the same URL to continue processing
    without leaving the "set" in the browser history.
    """
    if "set_server_language" in request.GET:
        # Set the current server default language, and redirect (to clean browser history)
        if not request.is_admin:
            raise PermissionDenied(_("You don't have permissions to set the server's default language."))

        set_default_language(request, lang_code=request.GET["set_server_language"], global_set=True)

        # Redirect to the same URL, but without the GET param,
        #   to remove the language setting from the browser history.
        redirect_url = set_query_params(request.get_full_path(), {"set_server_language": None})
        return HttpResponseRedirect(redirect_url)

    elif "set_user_language" in request.GET:
        # Set the current user's session language, and redirect (to clean browser history)
        set_default_language(request, request.GET["set_user_language"], global_set=(request.is_logged_in and not request.is_django_user))

        # Redirect to the same URL, but without the GET param,
        #   to remove the language setting from the browser history.
        redirect_url = set_query_params(request.get_full_path(), {"set_user_language": None})
        return HttpResponseRedirect(redirect_url)

    if not "default_language" in request.session:
        # default_language has the following priority:
        #   facility user's individual setting
        #   config.Settings object's value
        #   settings' value
        request.session["default_language"] = select_best_available_language( \
            getattr(request.session.get("facility_user"), "default_language", None) \
            or Settings.get("default_language") \
            or settings.LANGUAGE_CODE
        )

    # Set this request's language based on the listed priority
    cur_lang = request.GET.get("lang") \
        or request.session.get("default_language")

    set_request_language(request, lang_code=cur_lang)
Beispiel #13
0
 def real_decorator_wrapper_fn(request, *args, **kwargs):
     if Device.get_own_device().is_registered():
         return handler(request, *args, **kwargs)
     else:
         messages.warning(
             request,
             _("In order to access %(resource_name)s, you must register your device first."
               % {"resource_name": unicode(resource_name)}))
         return HttpResponseRedirect(
             set_query_params(reverse('register_public_key'),
                              {'next': request.path}))
Beispiel #14
0
def set_language_data_from_request(request):
    """
    Process requests to set language, redirect to the same URL to continue processing
    without leaving the "set" in the browser history.
    """
    if "set_server_language" in request.GET:
        # Set the current server default language, and redirect (to clean browser history)
        if not request.is_admin:
            raise PermissionDenied(_("You don't have permissions to set the server's default language."))

        set_default_language_from_request(request, lang_code=request.GET["set_server_language"], global_set=True)

        # Redirect to the same URL, but without the GET param,
        #   to remove the language setting from the browser history.
        redirect_url = set_query_params(request.get_full_path(), {"set_server_language": None})
        return HttpResponseRedirect(redirect_url)

    elif "set_user_language" in request.GET:
        # Set the current user's session language, and redirect (to clean browser history)
        set_default_language_from_request(request, request.GET["set_user_language"], global_set=(request.is_logged_in and not request.is_django_user))

        # Redirect to the same URL, but without the GET param,
        #   to remove the language setting from the browser history.
        redirect_url = set_query_params(request.get_full_path(), {"set_user_language": None})
        return HttpResponseRedirect(redirect_url)

    if not "default_language" in request.session:
        # default_language has the following priority:
        #   facility user's individual setting
        #   config.Settings object's value
        #   settings' value
        request.session["default_language"] = select_best_available_language( \
            getattr(request.session.get("facility_user"), "default_language", None) \
            or get_default_language()
        )

    # Set this request's language based on the listed priority
    cur_lang = request.GET.get("lang") \
        or request.session.get("default_language")

    set_request_language(request, lang_code=cur_lang)
Beispiel #15
0
def login_view(request, *args, **kwargs):
    """
    Force lowercase of the username.

    Since we don't want things to change to the user (if something fails),
    we should try the new way first, then fall back to the old way
    """

    prev = None

    if request.method=="POST":
        users = User.objects.filter(username__iexact=request.POST["username"])
        nusers = users.count()

        # Coerce
        if nusers == 1 and users[0].username != request.POST["username"]:
            request.POST = copy.deepcopy(request.POST)
            request.POST['username'] = request.POST['username'].lower()

        prev = request.POST.get('prev') or request.META.get("HTTP_REFERER")

    prev = prev or request.META.get("HTTP_REFERER")

    # Note: prev used because referer is lost on a login / redirect.
    #   So paste it on the success redirect.
    redirect_url = request.REQUEST.get("next", reverse('org_management'))
    if prev:
        redirect_url = set_query_params(redirect_url, {"prev": prev})

    extra_context = {
        "redirect": {
            "name": REDIRECT_FIELD_NAME,
            "url": redirect_url,
        },
        "auth_password_reset_url": reverse("auth_password_reset"),
        "registration_register_url": reverse("registration_register") if not request.next else set_query_params(reverse("registration_register"), {"next": request.next}),
    }
    kwargs["extra_context"] = extra_context

    return auth_views.login(request, *args, **kwargs)
Beispiel #16
0
def add_group(request, facility):
    groups = FacilityGroup.objects.all()
    if request.method == 'POST' and request.is_admin:
        form = FacilityGroupForm(data=request.POST)
        if form.is_valid():
            form.instance.facility = facility
            form.save()

            redir_url = request.GET.get("prev") or reverse("add_facility_student")
            redir_url = set_query_params(redir_url, {"facility": facility.pk, "group": form.instance.pk})
            return HttpResponseRedirect(redir_url)

    elif request.method == 'POST' and not request.is_admin:
        messages.error(request, _("This mission is too important for me to allow you to jeopardize it."))
        return HttpResponseRedirect(reverse("login"))
    else:
        form = FacilityGroupForm()
    return {
        "form": form,
        "facility": facility,
        "groups": groups,
        "singlefacility": request.session["facility_count"] == 1,
    }
Beispiel #17
0
def update_all_central_callback(request):
    """
    Callback after authentication.

    Parses out the request token verification.
    Then finishes the request by getting an auth token.
    """
    if not "ACCESS_TOKEN" in request.session:
        finish_auth(request)

    exercises = get_api_resource(request, "/api/v1/user/exercises")
    videos = get_api_resource(request, "/api/v1/user/videos")
    node_cache = get_node_cache()

    # Collate videos
    video_logs = []
    for video in videos:
        # Assume that KA videos are all english-language, not dubbed (for now)
        video_id = youtube_id = video.get('video', {}).get('youtube_id', "")

        # Only save videos with progress
        if not video.get('seconds_watched', None):
            continue

        # Only save video logs for videos that we recognize.
        if video_id not in node_cache["Video"]:
            logging.warn("Skipping unknown video %s" % video_id)
            continue

        try:
            video_logs.append({
                "video_id": video_id,
                "youtube_id": youtube_id,
                "total_seconds_watched": video['seconds_watched'],
                "points": VideoLog.calc_points(video['seconds_watched'], video['duration']),
                "complete": video['completed'],
                "completion_timestamp": convert_ka_date(video['last_watched']) if video['completed'] else None,
            })
            logging.debug("Got video log for %s: %s" % (video_id, video_logs[-1]))
        except KeyError:  #
            logging.error("Could not save video log for data with missing values: %s" % video)

    # Collate exercises
    exercise_logs = []
    for exercise in exercises:
        # Only save exercises that have any progress.
        if not exercise.get('last_done', None):
            continue

        # Only save video logs for videos that we recognize.
        slug = exercise.get('exercise', "")
        if slug not in node_cache['Exercise']:
            logging.warn("Skipping unknown video %s" % slug)
            continue

        try:
            completed = exercise['streak'] >= 10
            basepoints = node_cache['Exercise'][slug][0]['basepoints']
            exercise_logs.append({
                "exercise_id": slug,
                "streak_progress": min(100, 100 * exercise['streak']/10),  # duplicates logic elsewhere
                "attempts": exercise['total_done'],
                "points": ExerciseLog.calc_points(basepoints, ncorrect=exercise['streak'], add_randomness=False),  # no randomness when importing from KA
                "complete": completed,
                "attempts_before_completion": exercise['total_done'] if not exercise['practiced'] else None,  #can't figure this out if they practiced after mastery.
                "completion_timestamp": convert_ka_date(exercise['proficient_date']) if completed else None,
            })
            logging.debug("Got exercise log for %s: %s" % (slug, exercise_logs[-1]))
        except KeyError:
            logging.error("Could not save exercise log for data with missing values: %s" % exercise)

    # POST the data back to the distributed server
    try:

        dthandler = lambda obj: obj.isoformat() if isinstance(obj, datetime.datetime) else None
        logging.debug("POST'ing to %s" % request.session["distributed_callback_url"])
        response = requests.post(
            request.session["distributed_callback_url"],
            cookies={ "csrftoken": request.session["distributed_csrf_token"] },
            data = {
                "csrfmiddlewaretoken": request.session["distributed_csrf_token"],
                "video_logs": json.dumps(video_logs, default=dthandler),
                "exercise_logs": json.dumps(exercise_logs, default=dthandler),
                "user_id": request.session["distributed_user_id"],
            }
        )
        logging.debug("Response (%d): %s" % (response.status_code, response.content))
    except requests.exceptions.ConnectionError as e:
        return HttpResponseRedirect(set_query_params(request.session["distributed_redirect_url"], {
            "message_type": "error",
            "message": _("Could not connect to your KA Lite installation to share Khan Academy data."),
            "message_id": "id_khanload",
        }))
    except Exception as e:
        return HttpResponseRedirect(set_query_params(request.session["distributed_redirect_url"], {
            "message_type": "error",
            "message": _("Failure to send data to your KA Lite installation: %s") % e,
            "message_id": "id_khanload",
        }))


    try:
        json_response = json.loads(response.content)
        if not isinstance(json_response, dict) or len(json_response) != 1:
            # Could not validate the message is a single key-value pair
            raise Exception(_("Unexpected response format from your KA Lite installation."))
        message_type = json_response.keys()[0]
        message = json_response.values()[0]
    except ValueError as e:
        message_type = "error"
        message = unicode(e)
    except Exception as e:
        message_type = "error"
        message = _("Loading json object: %s") % e

    # If something broke on the distribute d server, we are SCREWED.
    #   For now, just show the error to users.
    #
    # Ultimately, we have a message, would like to share with the distributed server.
#    if response.status_code != 200:
#        return HttpResponseServerError(response.content)

    return HttpResponseRedirect(set_query_params(request.session["distributed_redirect_url"], {
        "message_type": message_type,
        "message": message,
        "message_id": "id_khanload",
    }))
Beispiel #18
0
    def get_registration_url(self, **kwargs):

        if "device_key" not in kwargs:
            kwargs["device_key"] = urllib.quote(Device.get_own_device().public_key)

        return self.path_to_url(set_query_params(reverse("register_public_key"), kwargs))