mirror of
https://github.com/ae-utbm/sith.git
synced 2026-06-04 23:29:24 +00:00
use fragment for counter login
This commit is contained in:
@@ -1,53 +0,0 @@
|
||||
#
|
||||
# Copyright 2023 © AE UTBM
|
||||
# ae@utbm.fr / ae.info@utbm.fr
|
||||
#
|
||||
# This file is part of the website of the UTBM Student Association (AE UTBM),
|
||||
# https://ae.utbm.fr.
|
||||
#
|
||||
# You can find the source code of the website at https://github.com/ae-utbm/sith
|
||||
#
|
||||
# LICENSED UNDER THE GNU GENERAL PUBLIC LICENSE VERSION 3 (GPLv3)
|
||||
# SEE : https://raw.githubusercontent.com/ae-utbm/sith/master/LICENSE
|
||||
# OR WITHIN THE LOCAL FILE "LICENSE"
|
||||
#
|
||||
#
|
||||
|
||||
from django.http import HttpRequest, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.utils import timezone
|
||||
from django.utils.timezone import now
|
||||
from django.views.decorators.http import require_POST
|
||||
|
||||
from core.views.forms import LoginForm
|
||||
from counter.models import Counter, Permanency
|
||||
|
||||
|
||||
@require_POST
|
||||
def counter_login(request: HttpRequest, counter_id: int) -> HttpResponseRedirect:
|
||||
"""Log a user in a counter.
|
||||
|
||||
A successful login will result in the beginning of a counter duty
|
||||
for the user.
|
||||
"""
|
||||
counter = get_object_or_404(Counter, pk=counter_id)
|
||||
form = LoginForm(request, data=request.POST)
|
||||
if not form.is_valid():
|
||||
return redirect(counter.get_absolute_url() + "?credentials")
|
||||
user = form.get_user()
|
||||
if not counter.sellers.contains(user) or user in counter.barmen_list:
|
||||
return redirect(counter.get_absolute_url() + "?sellers")
|
||||
if len(counter.barmen_list) == 0:
|
||||
counter.gen_token()
|
||||
request.session["counter_token"] = counter.token
|
||||
counter.permanencies.create(user=user, start=timezone.now())
|
||||
return redirect(counter)
|
||||
|
||||
|
||||
@require_POST
|
||||
def counter_logout(request: HttpRequest, counter_id: int) -> HttpResponseRedirect:
|
||||
"""End the permanency of a user in this counter."""
|
||||
Permanency.objects.filter(
|
||||
counter=counter_id, user=request.POST["user_id"], end=None
|
||||
).update(end=now())
|
||||
return redirect("counter:details", counter_id=counter_id)
|
||||
+5
-10
@@ -14,6 +14,7 @@
|
||||
#
|
||||
from collections import defaultdict
|
||||
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.db import transaction
|
||||
from django.db.models import Q
|
||||
@@ -21,6 +22,7 @@ from django.http import Http404
|
||||
from django.shortcuts import get_object_or_404, redirect, resolve_url
|
||||
from django.urls import reverse
|
||||
from django.utils.safestring import SafeString
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views.generic import FormView
|
||||
from django.views.generic.detail import SingleObjectMixin
|
||||
from ninja.main import HttpRequest
|
||||
@@ -29,13 +31,7 @@ from core.auth.mixins import CanViewMixin
|
||||
from core.models import User
|
||||
from core.views.mixins import FragmentMixin, UseFragmentsMixin
|
||||
from counter.forms import BasketForm, RefillForm
|
||||
from counter.models import (
|
||||
Counter,
|
||||
Customer,
|
||||
ProductFormula,
|
||||
ReturnableProduct,
|
||||
Selling,
|
||||
)
|
||||
from counter.models import Counter, Customer, ProductFormula, ReturnableProduct, Selling
|
||||
from counter.utils import is_logged_in_counter
|
||||
from counter.views.mixins import CounterTabsMixin
|
||||
from counter.views.student_card import StudentCardFormFragment
|
||||
@@ -97,10 +93,9 @@ class CounterClick(
|
||||
raise PermissionDenied
|
||||
|
||||
if obj.type == "BAR" and (
|
||||
not obj.is_open
|
||||
or "counter_token" not in request.session
|
||||
or request.session["counter_token"] != obj.token
|
||||
not obj.is_open or request.session.get("counter_token", "") != obj.token
|
||||
):
|
||||
messages.error(request, _("You cannot click users on this counter"))
|
||||
return redirect(obj) # Redirect to counter
|
||||
|
||||
self.prices = list(obj.get_prices_for(self.customer))
|
||||
|
||||
+92
-53
@@ -15,78 +15,114 @@
|
||||
from datetime import timedelta
|
||||
|
||||
from django.conf import settings
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.http import HttpRequest, HttpResponseRedirect
|
||||
from django.shortcuts import redirect
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.safestring import SafeString
|
||||
from django.utils.timezone import now
|
||||
from django.views.decorators.http import require_POST
|
||||
from django.views.generic import DetailView
|
||||
from django.views.generic.edit import FormMixin, ProcessFormView
|
||||
from django.views.generic.detail import SingleObjectMixin
|
||||
from django.views.generic.edit import FormView
|
||||
|
||||
from core.auth.mixins import CanViewMixin
|
||||
from core.views.forms import LoginForm
|
||||
from counter.forms import GetUserForm
|
||||
from counter.models import Counter
|
||||
from core.views import FragmentMixin, UseFragmentsMixin
|
||||
from counter.forms import CounterLoginForm, GetUserForm
|
||||
from counter.models import Counter, Permanency
|
||||
from counter.utils import is_logged_in_counter
|
||||
from counter.views.mixins import CounterTabsMixin
|
||||
|
||||
|
||||
class CounterLoginFragment(FragmentMixin, SingleObjectMixin, FormView):
|
||||
model = Counter
|
||||
form_class = CounterLoginForm
|
||||
reload_on_redirect = True
|
||||
pk_url_kwarg = "counter_id"
|
||||
template_name = "counter/fragments/login.jinja"
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_form_kwargs(self):
|
||||
return super().get_form_kwargs() | {"counter": self.object}
|
||||
|
||||
def form_valid(self, form: CounterLoginForm):
|
||||
self.object.permanencies.create(user=form.get_user(), start=timezone.now())
|
||||
if not self.object.barmen_list:
|
||||
self.object.gen_token()
|
||||
self.request.session["counter_token"] = self.object.token
|
||||
self.success_url = reverse(
|
||||
"counter:details", kwargs={"counter_id": self.object.id}
|
||||
)
|
||||
return super().form_valid(form)
|
||||
|
||||
def render_fragment(self, request, **kwargs) -> SafeString:
|
||||
self.object = kwargs.pop("counter")
|
||||
return super().render_fragment(request, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
return super().get_context_data(**kwargs) | {
|
||||
"action": reverse("counter:login", kwargs={"counter_id": self.object.id})
|
||||
}
|
||||
|
||||
|
||||
@require_POST
|
||||
def counter_logout(request: HttpRequest, counter_id: int) -> HttpResponseRedirect:
|
||||
"""End the permanency of a user in this counter."""
|
||||
Permanency.objects.filter(
|
||||
counter=counter_id, user=request.POST["user_id"], end=None
|
||||
).update(end=F("activity"))
|
||||
return redirect("counter:details", counter_id=counter_id)
|
||||
|
||||
|
||||
class CounterMain(
|
||||
CounterTabsMixin, CanViewMixin, DetailView, ProcessFormView, FormMixin
|
||||
CounterTabsMixin, UseFragmentsMixin, CanViewMixin, SingleObjectMixin, FormView
|
||||
):
|
||||
"""The public (barman) view."""
|
||||
|
||||
model = Counter
|
||||
queryset = Counter.objects.annotate_is_open().exclude(type="EBOUTIC")
|
||||
template_name = "counter/counter_main.jinja"
|
||||
pk_url_kwarg = "counter_id"
|
||||
form_class = (
|
||||
GetUserForm # Form to enter a client code and get the corresponding user id
|
||||
)
|
||||
form_class = GetUserForm
|
||||
current_tab = "counter"
|
||||
|
||||
def get_queryset(self):
|
||||
return super().get_queryset().exclude(type="EBOUTIC")
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.object: Counter = self.get_object()
|
||||
if self.object.type != "BAR" and self.request.method.upper() == "POST":
|
||||
# barmen have to log in (thus do a POST request)
|
||||
# only if it is a bar.
|
||||
return self.http_method_not_allowed(request, *args, **kwargs)
|
||||
if self.object.type == "BAR":
|
||||
self.object.update_activity()
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
if self.object.type == "BAR" and not (
|
||||
"counter_token" in self.request.session
|
||||
and self.request.session["counter_token"] == self.object.token
|
||||
): # Check the token to avoid the bar to be stolen
|
||||
return HttpResponseRedirect(
|
||||
reverse_lazy(
|
||||
"counter:details",
|
||||
args=self.args,
|
||||
kwargs={"counter_id": self.object.id},
|
||||
)
|
||||
+ "?bad_location"
|
||||
)
|
||||
return super().post(request, *args, **kwargs)
|
||||
def get_fragment_context_data(self) -> dict[str, SafeString]:
|
||||
login_fragment = (
|
||||
CounterLoginFragment.as_fragment()(self.request, counter=self.object)
|
||||
if self.object.type == "BAR"
|
||||
else ""
|
||||
)
|
||||
return super().get_fragment_context_data() | {"login_fragment": login_fragment}
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""We handle here the login form for the barman."""
|
||||
if self.request.method == "POST":
|
||||
self.object = self.get_object()
|
||||
self.object.update_activity()
|
||||
kwargs = super().get_context_data(**kwargs)
|
||||
kwargs["login_form"] = LoginForm()
|
||||
kwargs["login_form"].fields["username"].widget.attrs["autofocus"] = True
|
||||
kwargs[
|
||||
"login_form"
|
||||
].cleaned_data = {} # add_error fails if there are no cleaned_data
|
||||
if "credentials" in self.request.GET:
|
||||
kwargs["login_form"].add_error(None, _("Bad credentials"))
|
||||
if "sellers" in self.request.GET:
|
||||
kwargs["login_form"].add_error(None, _("User is not barman"))
|
||||
kwargs["form"] = self.get_form()
|
||||
kwargs["form"].cleaned_data = {} # same as above
|
||||
if "bad_location" in self.request.GET:
|
||||
kwargs["form"].add_error(
|
||||
None, _("Bad location, someone is already logged in somewhere else")
|
||||
)
|
||||
if self.object.type == "BAR":
|
||||
kwargs["barmen"] = self.object.barmen_list
|
||||
elif self.request.user.is_authenticated:
|
||||
kwargs["barmen"] = [self.request.user]
|
||||
kwargs["can_click"] = (
|
||||
self.object.type == "BAR"
|
||||
and self.object.is_open
|
||||
and self.request.session.get("counter_token", "") == self.object.token
|
||||
) or (
|
||||
self.object.type == "OFFICE"
|
||||
and (
|
||||
self.object.sellers.contains(self.request.user)
|
||||
or self.object.club.has_rights_in_club(self.request.user)
|
||||
)
|
||||
)
|
||||
if "last_basket" in self.request.session:
|
||||
kwargs["last_basket"] = self.request.session.pop("last_basket")
|
||||
kwargs["last_customer"] = self.request.session.pop("last_customer")
|
||||
@@ -96,14 +132,17 @@ class CounterMain(
|
||||
)
|
||||
return kwargs
|
||||
|
||||
def form_valid(self, form):
|
||||
def form_valid(self, form: CounterLoginForm):
|
||||
"""We handle here the redirection, passing the user id of the asked customer."""
|
||||
self.kwargs["user_id"] = form.cleaned_data["user_id"]
|
||||
self.success_url = reverse(
|
||||
"counter:click",
|
||||
kwargs={
|
||||
"counter_id": self.kwargs["counter_id"],
|
||||
"user_id": form.cleaned_data["user_id"],
|
||||
},
|
||||
)
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy("counter:click", args=self.args, kwargs=self.kwargs)
|
||||
|
||||
|
||||
class CounterLastOperationsView(CounterTabsMixin, CanViewMixin, DetailView):
|
||||
"""Provide the last operations to allow barmen to delete them."""
|
||||
|
||||
Reference in New Issue
Block a user