views.py 6.22 KB
Newer Older
1
from datetime import datetime, timedelta
2
import logging
3
import json
4 5

from django.http import HttpResponse, HttpResponseRedirect, HttpResponseNotFound
Florent Chehab's avatar
Florent Chehab committed
6
from django.shortcuts import render
7
from django.utils.timezone import make_aware
8
from webpack_loader.utils import get_files
Florent Chehab's avatar
Florent Chehab committed
9

10 11
from backend_app.utils import clean_route
from backend_app.viewsets import ALL_VIEWSETS
12 13
from base_app.forms import UserForm
from base_app.models import User
14 15 16 17 18 19 20
from _cron_tasks import (
    update_currencies,
    update_utc_ent,
    update_extra_denormalization,
    clear_and_clean_sessions,
    update_daily_stats,
)
21
from stats_app.models import DailyConnections, DailyExchangeContributionsInfo
22 23

logger = logging.getLogger("django")
24

Florent Chehab's avatar
Florent Chehab committed
25

26 27 28 29
def get_bundle_loc(name):
    return "/".join(get_files(name)[0]["url"].split("/")[:-1]) + "/"


Florent Chehab's avatar
Florent Chehab committed
30 31 32 33 34 35
def index(request):
    """
    View to to display the index app that contains the JS / CSS
    The "template" displayed is in ./templates/index.html
    """

36 37
    # We give the user object so that we can access its id in JS
    # and fetch userData
38 39
    user = request.user

40
    # small hack to get the correct location of the frontend bundled files
41
    front_bundle_loc = get_bundle_loc("main")
42

43 44
    # We also retrieve the list of all routes endpoints
    endpoints = list(map(lambda v: clean_route(v.end_point_route), ALL_VIEWSETS))
45 46 47 48 49 50 51
    return render(
        request,
        "index.html",
        dict(user=user, endpoints=endpoints, front_bundle_loc=front_bundle_loc),
    )


52 53 54 55
def stats(request):
    """
    Render the view that displays stats
    """
56
    dataset = request.GET.get("dataset")
57 58
    date_min = request.GET.get("date_min")
    date_max = request.GET.get("date_max")
59

60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
    get_params_are_valid = True

    if (dataset != "daily_connections") and (dataset != "daily_exchange_contributions"):
        get_params_are_valid = False
        # set default dataset
        dataset = "daily_connections"

    try:
        date_min_parsed = datetime.strptime(date_min, "%Y-%m-%d")
        date_max_parsed = datetime.strptime(date_max, "%Y-%m-%d")
        if date_min < date_max:
            date_max_parsed, date_min_parsed = date_max_parsed, date_min_parsed
    except:  # noqa: E722
        get_params_are_valid = False
        now = make_aware(datetime.now())
        date_min = (now - timedelta(days=365)).strftime("%Y-%m-%d")
        date_max = now.strftime("%Y-%m-%d")

    if not get_params_are_valid:
        url = f"/stats/?dataset={dataset}&date_min={date_min}&date_max={date_max}"
        request_info = request.GET.get("request_info")

        if request_info:
            url = f"{url}&request_info={request_info}"

        return HttpResponseRedirect(url)
86 87 88

    if dataset == "daily_connections":
        daily_connections = DailyConnections.objects.filter(
89
            date__gte=date_min_parsed, date__lt=date_max_parsed
90
        )
91
        raw_data = [
92
            {"date": dc.date.strftime("%Y-%m-%d"), "nb_connections": dc.nb_connections}
93
            for dc in daily_connections
94
        ]
95 96 97

        cols = ["date", "nb_connections"]

98
    elif dataset == "daily_exchange_contributions":
99
        daily_contributions = DailyExchangeContributionsInfo.objects.filter(
100
            date__gte=date_min_parsed, date__lt=date_max_parsed
101 102
        ).prefetch_related("university")

103 104
        raw_data = [
            {
105
                "date": dc.date.strftime("%Y-%m-%d"),
106
                "type": dc.type,
107 108 109 110 111 112 113
                "university": f"{dc.university.pk} - {dc.university.name}",
                "major": dc.major,
                "minor": dc.minor,
                "exchange_semester": dc.exchange_semester,
                "nb_contributions": dc.nb_contributions,
            }
            for dc in daily_contributions
114 115 116 117
        ]

        cols = [
            "date",
118
            "type",
119 120 121 122 123
            "university",
            "major",
            "minor",
            "exchange_semester",
            "nb_contributions",
124 125
        ]
    else:
126
        raise NotImplementedError()
127

128
    stats_data = {c: [d[c] for d in raw_data] for c in cols}
129 130 131
    return render(request, "stats.html", dict(stats_data=json.dumps(stats_data)))


132 133 134 135 136 137 138 139 140 141 142
def rgpd_raw(request):
    """
    Render the view that displays only the RGPD conditions
    """
    return render(request, "rgpd_raw.html")


def cgu_rgpd(request):
    """
    Render the view that handles user accepting CGU and RGPD conditions
    """
143 144 145 146 147 148 149 150 151 152
    if request.method == "POST":
        user = User.objects.get(pk=request.user.pk)
        form = UserForm(request.POST, instance=user)
        if form.is_valid():
            user = form.save(commit=True)
            user.save()
    else:
        user = User.objects.get(pk=request.user.pk)
        form = UserForm(instance=user)

153
    if "next" in request.GET and user.has_validated_cgu_rgpd:
154 155 156
        # if the user has just validated everything, we redirect him to the location he requested
        return HttpResponseRedirect(request.GET["next"])
    else:
157
        return render(request, "cgu_rgpd.html", dict(user=user, form=form))
158 159 160 161 162 163 164 165 166 167


def banned(request):
    user = request.user
    if user.is_banned:
        return render(request, "banned.html", dict(user=user))
    else:
        return HttpResponseNotFound()


168 169 170 171 172 173 174 175 176 177 178
def media_files_view(request, path):
    """
    Media files are served by nginx only if the user is connected.
    The authentication checked is performed through the middleware
    so here we only need to return a dumb request with the right headers
    that will be read by nginx.
    """
    response = HttpResponse()
    del response["Content-Type"]
    response["X-Accel-Redirect"] = "/protected-assets/media/" + path
    return response
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194


def trigger_cron(request):
    """
    Render the view that displays cron tasks
    """
    if request.method == "POST":
        cron_task = request.POST.get("cron_name")
        if cron_task == "update_currencies":
            update_currencies()
        elif cron_task == "update_utc_ent":
            update_utc_ent()
        elif cron_task == "update_extra_denormalization":
            update_extra_denormalization()
        elif cron_task == "clear_and_clean_sessions":
            clear_and_clean_sessions()
195 196
        elif cron_task == "update_daily_stats":
            update_daily_stats()
197 198 199 200
        else:
            return HttpResponseNotFound()

    return render(request, "admin/trigger_cron.html")