Sith/core/views/user.py

889 lines
28 KiB
Python
Raw Permalink Normal View History

2023-04-06 11:08:42 +00:00
# -*- coding:utf-8 -*-
#
2023-04-06 11:08:42 +00:00
# Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr
# All contributors are listed in the CONTRIBUTORS file.
#
2023-04-06 11:08:42 +00:00
# This file is part of the website of the UTBM Student Association (AE UTBM),
# https://ae.utbm.fr.
#
2023-04-06 11:08:42 +00:00
# You can find the whole source code at https://github.com/ae-utbm/sith3
#
2023-04-06 11:08:42 +00:00
# LICENSED UNDER THE GNU GENERAL PUBLIC LICENSE VERSION 3 (GPLv3)
# SEE : https://raw.githubusercontent.com/ae-utbm/sith3/master/LICENSE
# OR WITHIN THE LOCAL FILE "LICENSE"
#
2023-04-06 11:08:42 +00:00
# PREVIOUSLY LICENSED UNDER THE MIT LICENSE,
# SEE : https://raw.githubusercontent.com/ae-utbm/sith3/master/LICENSE.old
# OR WITHIN THE LOCAL FILE "LICENSE.old"
#
2015-11-24 15:09:46 +00:00
# This file contains all the views that concern the user model
2024-06-24 11:07:36 +00:00
import logging
from datetime import date, timedelta
from django.conf import settings
2017-06-12 07:42:03 +00:00
from django.contrib.auth import views
from django.contrib.auth.forms import PasswordChangeForm
2017-06-12 07:42:03 +00:00
from django.core.exceptions import PermissionDenied, ValidationError
2024-06-24 11:07:36 +00:00
from django.forms import CheckboxSelectMultiple
from django.forms.models import modelform_factory
from django.http import Http404, HttpResponse
2024-06-24 11:07:36 +00:00
from django.shortcuts import get_object_or_404, redirect, render
from django.template.response import TemplateResponse
from django.urls import reverse, reverse_lazy
from django.utils.translation import gettext as _
2018-10-04 19:29:19 +00:00
from django.views.generic import (
CreateView,
DeleteView,
2024-06-24 11:07:36 +00:00
DetailView,
ListView,
TemplateView,
2018-10-04 19:29:19 +00:00
)
2024-06-24 11:07:36 +00:00
from django.views.generic.dates import MonthMixin, YearMixin
from django.views.generic.edit import UpdateView
from api.views.sas import all_pictures_of_user
2024-06-24 11:07:36 +00:00
from core.models import Gift, Preferences, SithFile, User
2018-10-04 19:29:19 +00:00
from core.views import (
CanEditMixin,
CanEditPropMixin,
2024-06-24 11:07:36 +00:00
CanViewMixin,
2018-10-04 19:29:19 +00:00
QuickNotifMixin,
2024-06-24 11:07:36 +00:00
TabedViewMixin,
UserIsLoggedMixin,
2018-10-04 19:29:19 +00:00
)
from core.views.forms import (
2024-06-24 11:07:36 +00:00
GiftForm,
2018-10-04 19:29:19 +00:00
LoginForm,
2024-06-24 11:07:36 +00:00
RegisteringForm,
2018-10-04 19:29:19 +00:00
UserGodfathersForm,
2024-06-24 11:07:36 +00:00
UserProfileForm,
2018-10-04 19:29:19 +00:00
)
from counter.forms import StudentCardForm
2024-06-24 11:07:36 +00:00
from subscription.models import Subscription
2017-05-10 20:17:05 +00:00
from trombi.views import UserTrombiForm
2015-11-24 15:09:46 +00:00
2017-06-12 07:42:03 +00:00
class SithLoginView(views.LoginView):
2015-11-25 16:03:18 +00:00
"""
The login View
2015-11-25 16:03:18 +00:00
"""
template_name = "core/login.jinja"
authentication_form = LoginForm
form_class = PasswordChangeForm
2015-11-25 16:03:18 +00:00
2017-06-12 07:42:03 +00:00
class SithPasswordChangeView(views.PasswordChangeView):
2015-11-25 16:03:18 +00:00
"""
Allows a user to change its password
2015-11-25 16:03:18 +00:00
"""
template_name = "core/password_change.jinja"
success_url = reverse_lazy("core:password_change_done")
2015-11-25 16:03:18 +00:00
2017-06-12 07:42:03 +00:00
class SithPasswordChangeDoneView(views.PasswordChangeDoneView):
2015-11-25 16:03:18 +00:00
"""
Allows a user to change its password
"""
template_name = "core/password_change_done.jinja"
2015-11-25 16:03:18 +00:00
2017-06-12 07:42:03 +00:00
def logout(request):
2015-11-25 16:03:18 +00:00
"""
The logout view
2015-11-25 16:03:18 +00:00
"""
return views.logout_then_login(request)
2015-11-25 16:03:18 +00:00
2017-06-12 07:42:03 +00:00
2016-08-13 15:15:45 +00:00
def password_root_change(request, user_id):
"""
Allows a root user to change someone's password
"""
2016-08-14 02:35:08 +00:00
if not request.user.is_root:
2016-08-13 15:15:45 +00:00
raise PermissionDenied
user = User.objects.filter(id=user_id).first()
if not user:
raise Http404("User not found")
if request.method == "POST":
form = views.SetPasswordForm(user=user, data=request.POST)
if form.is_valid():
form.save()
return redirect("core:password_change_done")
else:
form = views.SetPasswordForm(user=user)
2018-10-04 19:29:19 +00:00
return TemplateResponse(
request, "core/password_change.jinja", {"form": form, "target": user}
)
2016-08-13 15:15:45 +00:00
2017-06-12 07:42:03 +00:00
class SithPasswordResetView(views.PasswordResetView):
2015-11-26 10:27:52 +00:00
"""
Allows someone to enter an email adresse for resetting password
"""
2017-06-12 07:42:03 +00:00
template_name = "core/password_reset.jinja"
email_template_name = "core/password_reset_email.jinja"
success_url = reverse_lazy("core:password_reset_done")
2015-11-25 16:03:18 +00:00
class SithPasswordResetDoneView(views.PasswordResetDoneView):
2015-11-26 10:27:52 +00:00
"""
Confirm that the reset email has been sent
"""
2015-11-25 16:03:18 +00:00
template_name = "core/password_reset_done.jinja"
2017-06-12 07:42:03 +00:00
class SithPasswordResetConfirmView(views.PasswordResetConfirmView):
2015-11-26 10:27:52 +00:00
"""
Provide a reset password form
2015-11-26 10:27:52 +00:00
"""
template_name = "core/password_reset_confirm.jinja"
success_url = reverse_lazy("core:password_reset_complete")
2017-06-12 07:42:03 +00:00
2015-11-26 09:57:26 +00:00
class SithPasswordResetCompleteView(views.PasswordResetCompleteView):
2015-11-26 10:27:52 +00:00
"""
Confirm the password has sucessfully been reset
"""
template_name = "core/password_reset_complete.jinja"
2017-06-12 07:42:03 +00:00
2015-11-25 16:03:18 +00:00
2015-11-24 15:09:46 +00:00
def register(request):
2016-07-19 17:03:16 +00:00
context = {}
2018-10-04 19:29:19 +00:00
if request.method == "POST":
2015-11-24 15:09:46 +00:00
form = RegisteringForm(request.POST)
if form.is_valid():
2018-10-04 19:29:19 +00:00
logging.debug(
"Registering "
+ form.cleaned_data["first_name"]
+ form.cleaned_data["last_name"]
)
2015-11-24 15:09:46 +00:00
u = form.save()
2018-10-04 19:29:19 +00:00
context["user_registered"] = u
context["tests"] = "TEST_REGISTER_USER_FORM_OK"
2015-11-24 15:09:46 +00:00
form = RegisteringForm()
else:
2018-10-04 19:29:19 +00:00
context["error"] = "Erreur"
context["tests"] = "TEST_REGISTER_USER_FORM_FAIL"
2015-11-24 15:09:46 +00:00
else:
form = RegisteringForm()
2018-10-04 19:29:19 +00:00
context["form"] = form.as_p()
2016-02-01 16:35:55 +00:00
return render(request, "core/register.jinja", context)
2015-11-24 15:09:46 +00:00
2017-06-12 07:42:03 +00:00
class UserTabsMixin(TabedViewMixin):
def get_tabs_title(self):
return self.object.get_display_name()
def get_list_of_tabs(self):
user: User = self.object
tab_list = [
2018-10-04 19:29:19 +00:00
{
"url": reverse("core:user_profile", kwargs={"user_id": user.id}),
2018-10-04 19:29:19 +00:00
"slug": "infos",
"name": _("Infos"),
},
2018-10-04 19:29:19 +00:00
{
"url": reverse("core:user_godfathers", kwargs={"user_id": user.id}),
2018-10-04 19:29:19 +00:00
"slug": "godfathers",
2021-11-05 20:01:19 +00:00
"name": _("Family"),
},
2018-10-04 19:29:19 +00:00
{
"url": reverse("core:user_pictures", kwargs={"user_id": user.id}),
2018-10-04 19:29:19 +00:00
"slug": "pictures",
"name": _("Pictures"),
},
]
if settings.SITH_ENABLE_GALAXY and self.request.user.was_subscribed:
tab_list.append(
{
"url": reverse("galaxy:user", kwargs={"user_id": user.id}),
"slug": "galaxy",
"name": _("Galaxy"),
}
)
if self.request.user == user:
2018-10-04 19:29:19 +00:00
tab_list.append(
{"url": reverse("core:user_tools"), "slug": "tools", "name": _("Tools")}
)
if self.request.user.can_edit(user):
2018-10-04 19:29:19 +00:00
tab_list.append(
{
"url": reverse("core:user_edit", kwargs={"user_id": user.id}),
2018-10-04 19:29:19 +00:00
"slug": "edit",
"name": _("Edit"),
}
)
tab_list.append(
{
"url": reverse("core:user_prefs", kwargs={"user_id": user.id}),
2018-10-04 19:29:19 +00:00
"slug": "prefs",
"name": _("Preferences"),
}
)
if self.request.user.can_view(user):
2018-10-04 19:29:19 +00:00
tab_list.append(
{
"url": reverse("core:user_clubs", kwargs={"user_id": user.id}),
2018-10-04 19:29:19 +00:00
"slug": "clubs",
"name": _("Clubs"),
}
)
if self.request.user.is_owner(user):
2018-10-04 19:29:19 +00:00
tab_list.append(
{
"url": reverse("core:user_groups", kwargs={"user_id": user.id}),
2018-10-04 19:29:19 +00:00
"slug": "groups",
"name": _("Groups"),
}
)
try:
if user.customer and (
user == self.request.user
2018-10-04 19:29:19 +00:00
or self.request.user.is_in_group(
pk=settings.SITH_GROUP_ACCOUNTING_ADMIN_ID
2018-10-04 19:29:19 +00:00
)
or self.request.user.is_in_group(
name=settings.SITH_BAR_MANAGER["unix_name"]
+ settings.SITH_BOARD_SUFFIX
2018-10-04 19:29:19 +00:00
)
or self.request.user.is_root
):
tab_list.append(
{
"url": reverse("core:user_stats", kwargs={"user_id": user.id}),
2018-10-04 19:29:19 +00:00
"slug": "stats",
"name": _("Stats"),
}
)
tab_list.append(
{
"url": reverse(
"core:user_account", kwargs={"user_id": user.id}
2018-10-04 19:29:19 +00:00
),
"slug": "account",
"name": _("Account") + " (%s €)" % user.customer.amount,
2018-10-04 19:29:19 +00:00
}
)
2017-06-12 07:42:03 +00:00
except:
pass
return tab_list
2017-06-12 07:42:03 +00:00
class UserView(UserTabsMixin, CanViewMixin, DetailView):
2015-11-24 15:09:46 +00:00
"""
Display a user's profile
"""
2018-10-04 19:29:19 +00:00
2015-11-26 15:32:56 +00:00
model = User
pk_url_kwarg = "user_id"
context_object_name = "profile"
2016-02-01 16:35:55 +00:00
template_name = "core/user_detail.jinja"
2018-10-04 19:29:19 +00:00
current_tab = "infos"
2015-11-26 15:32:56 +00:00
2017-11-05 23:22:25 +00:00
def get_context_data(self, **kwargs):
kwargs = super(UserView, self).get_context_data(**kwargs)
2018-10-04 19:29:19 +00:00
kwargs["gift_form"] = GiftForm(
user_id=self.object.id, initial={"user": self.object}
)
2017-11-05 23:22:25 +00:00
return kwargs
2016-09-29 13:04:43 +00:00
2017-06-12 07:42:03 +00:00
2016-11-20 09:40:49 +00:00
class UserPicturesView(UserTabsMixin, CanViewMixin, DetailView):
"""
Display a user's pictures
"""
2018-10-04 19:29:19 +00:00
2016-11-20 09:40:49 +00:00
model = User
pk_url_kwarg = "user_id"
context_object_name = "profile"
template_name = "core/user_pictures.jinja"
2018-10-04 19:29:19 +00:00
current_tab = "pictures"
2016-09-29 13:04:43 +00:00
def get_context_data(self, **kwargs):
kwargs = super(UserPicturesView, self).get_context_data(**kwargs)
2018-10-04 19:29:19 +00:00
kwargs["albums"] = []
kwargs["pictures"] = {}
picture_qs = all_pictures_of_user(self.object)
last_album = None
for picture in picture_qs:
album = picture.parent
if album.id != last_album and album not in kwargs["albums"]:
2018-10-04 19:29:19 +00:00
kwargs["albums"].append(album)
kwargs["pictures"][album.id] = []
last_album = album.id
kwargs["pictures"][album.id].append(picture)
return kwargs
2017-06-12 07:42:03 +00:00
2018-06-10 16:43:39 +00:00
2023-01-09 21:07:03 +00:00
def delete_user_godfather(request, user_id, godfather_id, is_father):
user_is_admin = request.user.is_root or request.user.is_board_member
if user_id != request.user.id and not user_is_admin:
raise PermissionDenied()
user = get_object_or_404(User, id=user_id)
to_remove = get_object_or_404(User, id=godfather_id)
if is_father:
user.godfathers.remove(to_remove)
else:
2023-01-09 21:07:03 +00:00
user.godchildren.remove(to_remove)
2018-10-04 19:29:19 +00:00
return redirect("core:user_godfathers", user_id=user_id)
2018-06-10 16:43:39 +00:00
2016-09-19 18:29:43 +00:00
class UserGodfathersView(UserTabsMixin, CanViewMixin, DetailView):
"""
Display a user's godfathers
"""
2018-10-04 19:29:19 +00:00
2016-09-19 18:29:43 +00:00
model = User
pk_url_kwarg = "user_id"
context_object_name = "profile"
template_name = "core/user_godfathers.jinja"
2018-10-04 19:29:19 +00:00
current_tab = "godfathers"
2016-09-19 18:29:43 +00:00
def post(self, request, *args, **kwargs):
self.object = self.get_object()
self.form = UserGodfathersForm(request.POST)
2018-10-04 19:29:19 +00:00
if self.form.is_valid() and self.form.cleaned_data["user"] != self.object:
if self.form.cleaned_data["type"] == "godfather":
self.object.godfathers.add(self.form.cleaned_data["user"])
2016-09-19 18:29:43 +00:00
self.object.save()
else:
2018-10-04 19:29:19 +00:00
self.object.godchildren.add(self.form.cleaned_data["user"])
2016-09-19 18:29:43 +00:00
self.object.save()
self.form = UserGodfathersForm()
return super(UserGodfathersView, self).get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
kwargs = super(UserGodfathersView, self).get_context_data(**kwargs)
try:
2018-10-04 19:29:19 +00:00
kwargs["form"] = self.form
2016-09-19 18:29:43 +00:00
except:
2018-10-04 19:29:19 +00:00
kwargs["form"] = UserGodfathersForm()
2016-09-19 18:29:43 +00:00
return kwargs
2018-10-04 19:29:19 +00:00
class UserGodfathersTreeView(UserTabsMixin, CanViewMixin, DetailView):
"""
Display a user's family tree
"""
2018-10-04 19:29:19 +00:00
model = User
pk_url_kwarg = "user_id"
context_object_name = "profile"
template_name = "core/user_godfathers_tree.jinja"
2018-10-04 19:29:19 +00:00
current_tab = "godfathers"
def get_context_data(self, **kwargs):
kwargs = super(UserGodfathersTreeView, self).get_context_data(**kwargs)
if "descent" in self.request.GET:
2018-10-04 19:29:19 +00:00
kwargs["param"] = "godchildren"
else:
2018-10-04 19:29:19 +00:00
kwargs["param"] = "godfathers"
kwargs["members_set"] = set()
return kwargs
2018-10-04 19:29:19 +00:00
class UserGodfathersTreePictureView(CanViewMixin, DetailView):
"""
Display a user's tree as a picture
"""
2018-10-04 19:29:19 +00:00
model = User
pk_url_kwarg = "user_id"
def build_complex_graph(self):
import pygraphviz as pgv
2018-10-04 19:29:19 +00:00
self.depth = int(self.request.GET.get("depth", 4))
if self.param == "godfathers":
self.graph = pgv.AGraph(strict=False, directed=True, rankdir="BT")
else:
self.graph = pgv.AGraph(strict=False, directed=True)
family = set()
self.level = 1
# Since the tree isn't very deep, we can build it recursively
def crawl_family(user):
2018-10-04 19:29:19 +00:00
if self.level > self.depth:
return
self.level += 1
for u in user.__getattribute__(self.param).all():
self.graph.add_edge(user.get_short_name(), u.get_short_name())
if u not in family:
family.add(u)
crawl_family(u)
self.level -= 1
2018-10-04 19:29:19 +00:00
self.graph.add_node(self.object.get_short_name())
family.add(self.object)
crawl_family(self.object)
def build_family_graph(self):
import pygraphviz as pgv
2018-10-04 19:29:19 +00:00
self.graph = pgv.AGraph(strict=False, directed=True)
self.graph.add_node(self.object.get_short_name())
for u in self.object.godfathers.all():
self.graph.add_edge(u.get_short_name(), self.object.get_short_name())
for u in self.object.godchildren.all():
self.graph.add_edge(self.object.get_short_name(), u.get_short_name())
def get(self, request, *args, **kwargs):
self.object = self.get_object()
if "descent" in self.request.GET:
self.param = "godchildren"
elif "ancestors" in self.request.GET:
self.param = "godfathers"
else:
self.param = "family"
if self.param == "family":
self.build_family_graph()
else:
self.build_complex_graph()
# Pimp the graph before display
2018-10-04 19:29:19 +00:00
self.graph.node_attr["color"] = "lightblue"
self.graph.node_attr["style"] = "filled"
main_node = self.graph.get_node(self.object.get_short_name())
2018-10-04 19:29:19 +00:00
main_node.attr["color"] = "sandybrown"
main_node.attr["shape"] = "rect"
if self.param == "godchildren":
2018-10-04 19:29:19 +00:00
self.graph.graph_attr["label"] = _("Godchildren")
elif self.param == "godfathers":
2021-11-05 20:01:19 +00:00
self.graph.graph_attr["label"] = _("Family")
else:
2018-10-04 19:29:19 +00:00
self.graph.graph_attr["label"] = _("Family")
img = self.graph.draw(format="png", prog="dot")
return HttpResponse(img, content_type="image/png")
2017-06-12 07:42:03 +00:00
2018-10-04 19:29:19 +00:00
class UserStatsView(UserTabsMixin, CanViewMixin, DetailView):
"""
Display a user's stats
"""
2018-10-04 19:29:19 +00:00
model = User
pk_url_kwarg = "user_id"
context_object_name = "profile"
template_name = "core/user_stats.jinja"
2018-10-04 19:29:19 +00:00
current_tab = "stats"
2017-03-27 23:03:31 +00:00
def dispatch(self, request, *arg, **kwargs):
profile = self.get_object()
2017-03-28 12:39:52 +00:00
if not hasattr(profile, "customer"):
raise Http404
2018-10-04 19:29:19 +00:00
if not (
profile == request.user
or request.user.is_in_group(pk=settings.SITH_GROUP_ACCOUNTING_ADMIN_ID)
2018-10-04 19:29:19 +00:00
or request.user.is_in_group(
name=settings.SITH_BAR_MANAGER["unix_name"] + settings.SITH_BOARD_SUFFIX
2018-10-04 19:29:19 +00:00
)
or request.user.is_root
):
2017-03-27 23:03:31 +00:00
raise PermissionDenied
return super(UserStatsView, self).dispatch(request, *arg, **kwargs)
def get_context_data(self, **kwargs):
kwargs = super(UserStatsView, self).get_context_data(**kwargs)
2016-09-22 09:09:15 +00:00
from django.db.models import Sum
2018-10-04 19:29:19 +00:00
2024-06-24 11:07:36 +00:00
from counter.models import Counter
2016-08-19 00:53:44 +00:00
foyer = Counter.objects.filter(name="Foyer").first()
mde = Counter.objects.filter(name="MDE").first()
gommette = Counter.objects.filter(name="La Gommette").first()
2017-06-12 07:42:03 +00:00
semester_start = Subscription.compute_start(d=date.today(), duration=3)
2018-10-04 19:29:19 +00:00
kwargs["total_perm_time"] = sum(
[p.end - p.start for p in self.object.permanencies.exclude(end=None)],
timedelta(),
)
kwargs["total_foyer_time"] = sum(
[
p.end - p.start
for p in self.object.permanencies.filter(counter=foyer).exclude(
end=None
)
],
timedelta(),
)
kwargs["total_mde_time"] = sum(
[
p.end - p.start
for p in self.object.permanencies.filter(counter=mde).exclude(end=None)
],
timedelta(),
)
kwargs["total_gommette_time"] = sum(
[
p.end - p.start
for p in self.object.permanencies.filter(counter=gommette).exclude(
end=None
)
],
timedelta(),
)
kwargs["total_foyer_buyings"] = sum(
[
b.unit_price * b.quantity
for b in self.object.customer.buyings.filter(
counter=foyer, date__gte=semester_start
)
]
)
kwargs["total_mde_buyings"] = sum(
[
b.unit_price * b.quantity
for b in self.object.customer.buyings.filter(
counter=mde, date__gte=semester_start
)
]
)
kwargs["total_gommette_buyings"] = sum(
[
b.unit_price * b.quantity
for b in self.object.customer.buyings.filter(
counter=gommette, date__gte=semester_start
)
]
)
kwargs["top_product"] = (
self.object.customer.buyings.values("product__name")
.annotate(product_sum=Sum("quantity"))
.exclude(product_sum=None)
.order_by("-product_sum")
.all()[:10]
)
return kwargs
2017-06-12 07:42:03 +00:00
2016-08-14 17:28:14 +00:00
class UserMiniView(CanViewMixin, DetailView):
"""
Display a user's profile
"""
2018-10-04 19:29:19 +00:00
2016-08-14 17:28:14 +00:00
model = User
pk_url_kwarg = "user_id"
context_object_name = "profile"
template_name = "core/user_mini.jinja"
2017-06-12 07:42:03 +00:00
2016-10-27 16:39:40 +00:00
class UserListView(ListView, CanEditPropMixin):
2015-11-26 15:32:56 +00:00
"""
Displays the user list
"""
2018-10-04 19:29:19 +00:00
2015-11-26 15:32:56 +00:00
model = User
2016-02-01 16:35:55 +00:00
template_name = "core/user_list.jinja"
2015-11-26 15:32:56 +00:00
2017-06-12 07:42:03 +00:00
class UserUploadProfilePictView(CanEditMixin, DetailView):
"""
Handle the upload of the profile picture taken with webcam in navigator
"""
2018-10-04 19:29:19 +00:00
model = User
pk_url_kwarg = "user_id"
template_name = "core/user_edit.jinja"
def post(self, request, *args, **kwargs):
from io import BytesIO
2024-06-24 11:07:36 +00:00
from PIL import Image
2018-10-04 19:29:19 +00:00
2024-06-24 11:07:36 +00:00
from core.utils import resize_image
self.object = self.get_object()
if self.object.profile_pict:
raise ValidationError(_("User already has a profile picture"))
2018-10-04 19:29:19 +00:00
f = request.FILES["new_profile_pict"]
parent = SithFile.objects.filter(parent=None, name="profiles").first()
2017-06-12 07:42:03 +00:00
name = str(self.object.id) + "_profile.jpg" # Webcamejs uploads JPGs
im = Image.open(BytesIO(f.read()))
2018-10-04 19:29:19 +00:00
new_file = SithFile(
parent=parent,
name=name,
file=resize_image(im, 400, f.content_type.split("/")[-1]),
owner=self.object,
is_folder=False,
mime_type=f.content_type,
size=f.size,
2018-10-04 19:29:19 +00:00
)
new_file.file.name = name
new_file.save()
self.object.profile_pict = new_file
self.object.save()
return redirect("core:user_edit", user_id=self.object.id)
2017-06-12 07:42:03 +00:00
class UserUpdateProfileView(UserTabsMixin, CanEditMixin, UpdateView):
2015-11-26 15:32:56 +00:00
"""
Edit a user's profile
"""
2018-10-04 19:29:19 +00:00
2015-11-26 15:32:56 +00:00
model = User
pk_url_kwarg = "user_id"
2016-02-01 16:35:55 +00:00
template_name = "core/user_edit.jinja"
form_class = UserProfileForm
current_tab = "edit"
2018-10-04 19:29:19 +00:00
edit_once = ["profile_pict", "date_of_birth", "first_name", "last_name"]
board_only = []
2016-10-15 00:33:38 +00:00
def remove_restricted_fields(self, request):
"""
Removes edit_once and board_only fields
"""
for i in self.edit_once:
2018-10-04 19:29:19 +00:00
if getattr(self.form.instance, i) and not (
request.user.is_board_member or request.user.is_root
):
self.form.fields.pop(i, None)
2016-10-15 00:33:38 +00:00
for i in self.board_only:
if not (request.user.is_board_member or request.user.is_root):
self.form.fields.pop(i, None)
def get(self, request, *args, **kwargs):
self.object = self.get_object()
self.form = self.get_form()
2016-10-15 00:33:38 +00:00
self.remove_restricted_fields(request)
return self.render_to_response(self.get_context_data(form=self.form))
def post(self, request, *args, **kwargs):
self.object = self.get_object()
self.form = self.get_form()
2016-10-15 00:33:38 +00:00
self.remove_restricted_fields(request)
files = request.FILES.items()
self.form.process(files)
2018-10-04 19:29:19 +00:00
if (
request.user.is_authenticated
2018-10-04 19:29:19 +00:00
and request.user.can_edit(self.object)
and self.form.is_valid()
):
return super(UserUpdateProfileView, self).form_valid(self.form)
return self.form_invalid(self.form)
def get_context_data(self, **kwargs):
kwargs = super(UserUpdateProfileView, self).get_context_data(**kwargs)
2018-10-04 19:29:19 +00:00
kwargs["profile"] = self.form.instance
kwargs["form"] = self.form
return kwargs
2015-11-26 15:32:56 +00:00
2017-06-12 07:42:03 +00:00
2016-10-05 11:08:51 +00:00
class UserClubView(UserTabsMixin, CanViewMixin, DetailView):
"""
Display the user's club(s)
"""
2018-10-04 19:29:19 +00:00
2016-10-05 11:08:51 +00:00
model = User
context_object_name = "profile"
pk_url_kwarg = "user_id"
template_name = "core/user_clubs.jinja"
current_tab = "clubs"
2017-06-12 07:42:03 +00:00
2017-01-11 00:34:16 +00:00
class UserPreferencesView(UserTabsMixin, CanEditMixin, UpdateView):
"""
Edit a user's preferences
"""
2018-10-04 19:29:19 +00:00
model = User
2017-01-11 00:34:16 +00:00
pk_url_kwarg = "user_id"
2017-05-09 21:42:01 +00:00
template_name = "core/user_preferences.jinja"
2018-10-04 19:29:19 +00:00
form_class = modelform_factory(
Preferences, fields=["receive_weekmail", "notify_on_click", "notify_on_refill"]
)
2017-01-11 00:34:16 +00:00
context_object_name = "profile"
current_tab = "prefs"
def get_object(self, queryset=None):
2018-10-04 19:29:19 +00:00
user = get_object_or_404(User, pk=self.kwargs["user_id"])
return user
def get_form_kwargs(self):
kwargs = super(UserPreferencesView, self).get_form_kwargs()
pref = self.object.preferences
2018-10-04 19:29:19 +00:00
kwargs.update({"instance": pref})
return kwargs
2017-01-11 00:34:16 +00:00
2017-05-09 21:42:01 +00:00
def get_context_data(self, **kwargs):
kwargs = super(UserPreferencesView, self).get_context_data(**kwargs)
if not (
hasattr(self.object, "trombi_user") and self.request.user.trombi_user.trombi
):
2018-10-04 19:29:19 +00:00
kwargs["trombi_form"] = UserTrombiForm()
if hasattr(self.object, "customer"):
kwargs["student_card_form"] = StudentCardForm()
2017-05-09 21:42:01 +00:00
return kwargs
2017-06-12 07:42:03 +00:00
class UserUpdateGroupView(UserTabsMixin, CanEditPropMixin, UpdateView):
2015-11-26 15:32:56 +00:00
"""
Edit a user's groups
"""
2018-10-04 19:29:19 +00:00
2015-11-26 15:32:56 +00:00
model = User
pk_url_kwarg = "user_id"
template_name = "core/user_group.jinja"
2018-10-04 19:29:19 +00:00
form_class = modelform_factory(
User, fields=["groups"], widgets={"groups": CheckboxSelectMultiple}
)
2016-02-01 16:35:55 +00:00
context_object_name = "profile"
current_tab = "groups"
2015-11-26 15:32:56 +00:00
2017-06-12 07:42:03 +00:00
class UserToolsView(QuickNotifMixin, UserTabsMixin, UserIsLoggedMixin, TemplateView):
"""
Displays the logged user's tools
"""
2018-10-04 19:29:19 +00:00
2016-02-01 16:35:55 +00:00
template_name = "core/user_tools.jinja"
current_tab = "tools"
2016-08-05 07:52:19 +00:00
def get_context_data(self, **kwargs):
self.object = self.request.user
from launderette.models import Launderette
2018-10-04 19:29:19 +00:00
kwargs = super(UserToolsView, self).get_context_data(**kwargs)
2018-10-04 19:29:19 +00:00
kwargs["launderettes"] = Launderette.objects.all()
kwargs["profile"] = self.request.user
kwargs["object"] = self.request.user
return kwargs
2017-06-12 07:42:03 +00:00
2016-09-06 19:47:15 +00:00
class UserAccountBase(UserTabsMixin, DetailView):
2016-08-05 07:52:19 +00:00
"""
2016-09-06 19:47:15 +00:00
Base class for UserAccount
2016-08-05 07:52:19 +00:00
"""
2018-10-04 19:29:19 +00:00
2016-08-05 07:52:19 +00:00
model = User
pk_url_kwarg = "user_id"
current_tab = "account"
2016-08-05 07:52:19 +00:00
2017-06-12 07:42:03 +00:00
def dispatch(self, request, *arg, **kwargs): # Manually validates the rights
2016-09-06 19:47:15 +00:00
res = super(UserAccountBase, self).dispatch(request, *arg, **kwargs)
2018-10-04 19:29:19 +00:00
if (
self.object == request.user
or request.user.is_in_group(pk=settings.SITH_GROUP_ACCOUNTING_ADMIN_ID)
2018-10-04 19:29:19 +00:00
or request.user.is_in_group(
name=settings.SITH_BAR_MANAGER["unix_name"] + settings.SITH_BOARD_SUFFIX
2018-10-04 19:29:19 +00:00
)
or request.user.is_root
):
2016-08-05 07:52:19 +00:00
return res
raise PermissionDenied
2017-06-12 07:42:03 +00:00
2016-09-06 19:47:15 +00:00
class UserAccountView(UserAccountBase):
"""
Display a user's account
"""
2018-10-04 19:29:19 +00:00
2016-09-06 19:47:15 +00:00
template_name = "core/user_account.jinja"
def expense_by_month(self, obj, calc):
2016-09-06 16:43:39 +00:00
stats = []
2018-10-04 19:29:19 +00:00
for year in obj.datetimes("date", "year", order="DESC"):
2016-09-06 16:43:39 +00:00
stats.append([])
2016-09-08 01:21:39 +00:00
i = 0
for month in obj.filter(date__year=year.year).datetimes(
2018-10-04 19:29:19 +00:00
"date", "month", order="DESC"
):
q = obj.filter(date__year=month.year, date__month=month.month)
stats[i].append({"sum": sum([calc(p) for p in q]), "date": month})
2016-09-08 01:21:39 +00:00
i += 1
2016-09-06 16:43:39 +00:00
return stats
2016-09-06 19:47:15 +00:00
def invoices_calc(self, query):
t = 0
for it in query.items.all():
t += it.quantity * it.product_unit_price
return t
2016-08-05 07:52:19 +00:00
def get_context_data(self, **kwargs):
kwargs = super(UserAccountView, self).get_context_data(**kwargs)
2018-10-04 19:29:19 +00:00
kwargs["profile"] = self.object
2016-08-05 07:52:19 +00:00
try:
2018-10-04 19:29:19 +00:00
kwargs["customer"] = self.object.customer
kwargs["buyings_month"] = self.expense_by_month(
self.object.customer.buyings, (lambda q: q.unit_price * q.quantity)
2016-09-06 19:47:15 +00:00
)
2018-10-04 19:29:19 +00:00
kwargs["invoices_month"] = self.expense_by_month(
self.object.customer.user.invoices, self.invoices_calc
2016-09-06 19:47:15 +00:00
)
2018-10-04 19:29:19 +00:00
kwargs["refilling_month"] = self.expense_by_month(
self.object.customer.refillings, (lambda q: q.amount)
2016-09-06 19:47:15 +00:00
)
2018-10-04 19:29:19 +00:00
kwargs["etickets"] = self.object.customer.buyings.exclude(
product__eticket=None
).all()
except Exception as e:
print(repr(e))
2016-08-05 07:52:19 +00:00
return kwargs
2017-06-12 07:42:03 +00:00
2016-09-06 19:47:15 +00:00
class UserAccountDetailView(UserAccountBase, YearMixin, MonthMixin):
"""
Display a user's account for month
"""
2018-10-04 19:29:19 +00:00
2016-09-06 19:47:15 +00:00
template_name = "core/user_account_detail.jinja"
def get_context_data(self, **kwargs):
kwargs = super(UserAccountDetailView, self).get_context_data(**kwargs)
2018-10-04 19:29:19 +00:00
kwargs["profile"] = self.object
kwargs["year"] = self.get_year()
kwargs["month"] = self.get_month()
2016-09-06 19:47:15 +00:00
try:
2018-10-04 19:29:19 +00:00
kwargs["customer"] = self.object.customer
2016-09-06 19:47:15 +00:00
except:
pass
2018-10-04 19:29:19 +00:00
kwargs["tab"] = "account"
2016-09-06 19:47:15 +00:00
return kwargs
2017-11-05 23:22:25 +00:00
class GiftCreateView(CreateView):
form_class = GiftForm
2018-10-04 19:29:19 +00:00
template_name = "core/create.jinja"
2017-11-05 23:22:25 +00:00
def dispatch(self, request, *args, **kwargs):
if not (request.user.is_board_member or request.user.is_root):
raise PermissionDenied
2018-10-04 19:29:19 +00:00
self.user = get_object_or_404(User, pk=kwargs["user_id"])
2017-11-05 23:22:25 +00:00
return super(GiftCreateView, self).dispatch(request, *args, **kwargs)
def get_initial(self):
2018-10-04 19:29:19 +00:00
return {"user": self.user}
2017-11-05 23:22:25 +00:00
def get_form_kwargs(self):
kwargs = super(GiftCreateView, self).get_form_kwargs()
2018-10-04 19:29:19 +00:00
kwargs["user_id"] = self.user.id
2017-11-05 23:22:25 +00:00
return kwargs
def get_success_url(self):
2018-10-04 19:29:19 +00:00
return reverse_lazy("core:user_profile", kwargs={"user_id": self.user.id})
2017-11-05 23:22:25 +00:00
class GiftDeleteView(CanEditPropMixin, DeleteView):
model = Gift
pk_url_kwarg = "gift_id"
2018-10-04 19:29:19 +00:00
template_name = "core/delete_confirm.jinja"
2017-11-05 23:22:25 +00:00
def dispatch(self, request, *args, **kwargs):
2018-10-04 19:29:19 +00:00
self.user = get_object_or_404(User, pk=kwargs["user_id"])
2017-11-05 23:22:25 +00:00
return super(GiftDeleteView, self).dispatch(request, *args, **kwargs)
def get_success_url(self):
2018-10-04 19:29:19 +00:00
return reverse_lazy("core:user_profile", kwargs={"user_id": self.user.id})