mirror of
https://github.com/ae-utbm/sith.git
synced 2026-06-13 19:49:22 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 519a7758c5 |
+7
-5
@@ -39,6 +39,7 @@ from counter.models import (
|
|||||||
Customer,
|
Customer,
|
||||||
Eticket,
|
Eticket,
|
||||||
InvoiceCall,
|
InvoiceCall,
|
||||||
|
Permanency,
|
||||||
Price,
|
Price,
|
||||||
Product,
|
Product,
|
||||||
ProductFormula,
|
ProductFormula,
|
||||||
@@ -151,12 +152,13 @@ class CounterLoginForm(LoginForm):
|
|||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
message=_("You are not a barman of this counter."), code="not_barman"
|
message=_("You are not a barman of this counter."), code="not_barman"
|
||||||
)
|
)
|
||||||
|
if Permanency.objects.filter(end=None, user=user).exists():
|
||||||
if user in self.request.barmen:
|
if user in self.request.barmen:
|
||||||
message = (
|
message = _("You are already logged in this counter.")
|
||||||
_("You are already logged in this counter.")
|
elif user in self.counter.barmen_list:
|
||||||
if user in self.counter.barmen_list
|
message = _("You are already logged in another counter.")
|
||||||
else _("You are already logged in another counter.")
|
else:
|
||||||
)
|
message = _("You are already logged on another device")
|
||||||
raise ValidationError(message=message, code="already_logged_in")
|
raise ValidationError(message=message, code="already_logged_in")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+21
-19
@@ -1,8 +1,7 @@
|
|||||||
from typing import TYPE_CHECKING, Callable
|
from typing import TYPE_CHECKING, Callable
|
||||||
|
|
||||||
from django.db.models import Exists, OuterRef
|
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.utils.functional import SimpleLazyObject, empty
|
from django.utils.functional import SimpleLazyObject
|
||||||
|
|
||||||
from core.models import User
|
from core.models import User
|
||||||
from counter.models import Permanency
|
from counter.models import Permanency
|
||||||
@@ -11,20 +10,31 @@ if TYPE_CHECKING:
|
|||||||
from django.contrib.sessions.backends.base import SessionBase
|
from django.contrib.sessions.backends.base import SessionBase
|
||||||
|
|
||||||
|
|
||||||
SESSION_BARMEN_KEY = "barmen_ids"
|
SESSION_PERMANENCES_KEY = "permanence_ids"
|
||||||
|
|
||||||
|
|
||||||
def get_cached_barmen(request: HttpRequest) -> set[User]:
|
def get_cached_barmen(request: HttpRequest) -> set[User]:
|
||||||
if not hasattr(request, "_cached_barmen"):
|
if not hasattr(request, "_cached_barmen"):
|
||||||
session: SessionBase = request.session
|
session: SessionBase = request.session
|
||||||
barmen_ids = session.get(SESSION_BARMEN_KEY, [])
|
|
||||||
if barmen_ids:
|
if session_ids := session.get(SESSION_PERMANENCES_KEY, None):
|
||||||
request._cached_barmen = set(
|
# Get ongoing permanences which id is in session.
|
||||||
User.objects.filter(
|
# Note : we store permanence ids rather than user id to be sure
|
||||||
Exists(Permanency.objects.filter(user=OuterRef("pk"), end=None)),
|
# not to wrongfully mark someone as logged here,
|
||||||
id__in=barmen_ids,
|
# even if it logged out then logged in elsewhere.
|
||||||
)
|
permanences = (
|
||||||
|
Permanency.objects.filter(end=None, id__in=session_ids)
|
||||||
|
.order_by("id")
|
||||||
|
.select_related("user")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# if the list of permanences occurring on this device has changed
|
||||||
|
# since the last page load, change the ids stored in session
|
||||||
|
real_ids = [p.id for p in permanences]
|
||||||
|
if real_ids != session_ids:
|
||||||
|
session[SESSION_PERMANENCES_KEY] = real_ids
|
||||||
|
|
||||||
|
request._cached_barmen = {p.user for p in permanences}
|
||||||
else:
|
else:
|
||||||
request._cached_barmen = set()
|
request._cached_barmen = set()
|
||||||
|
|
||||||
@@ -53,12 +63,4 @@ class BarmenMiddleware:
|
|||||||
def __call__(self, request: HttpRequest):
|
def __call__(self, request: HttpRequest):
|
||||||
request.barmen = SimpleLazyObject(lambda: get_cached_barmen(request))
|
request.barmen = SimpleLazyObject(lambda: get_cached_barmen(request))
|
||||||
|
|
||||||
response = self.get_response(request)
|
return self.get_response(request)
|
||||||
|
|
||||||
if request.barmen._wrapped is not empty and {
|
|
||||||
b.id for b in request.barmen
|
|
||||||
} != set(request.session.get(SESSION_BARMEN_KEY, [])):
|
|
||||||
# update the session data only if `session.barmen`
|
|
||||||
# has been accessed and modified.
|
|
||||||
request.session[SESSION_BARMEN_KEY] = [b.id for b in request.barmen]
|
|
||||||
return response
|
|
||||||
|
|||||||
+1
-1
@@ -1105,7 +1105,7 @@ class Permanency(models.Model):
|
|||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
)
|
)
|
||||||
start = models.DateTimeField(_("start date"))
|
start = models.DateTimeField(_("start date"))
|
||||||
end = models.DateTimeField(_("end date"), null=True, db_index=True)
|
end = models.DateTimeField(_("end date"), null=True, blank=True, db_index=True)
|
||||||
activity = models.DateTimeField(_("last activity date"), auto_now=True)
|
activity = models.DateTimeField(_("last activity date"), auto_now=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
@@ -760,10 +760,10 @@ class TestBarmanConnection(TestCase):
|
|||||||
assert last_perm.counter == self.counter
|
assert last_perm.counter == self.counter
|
||||||
assert last_perm.user == self.barman
|
assert last_perm.user == self.barman
|
||||||
assert last_perm.end is None
|
assert last_perm.end is None
|
||||||
assert self.barman in response.wsgi_request.barmen
|
|
||||||
response = self.client.get(
|
response = self.client.get(
|
||||||
self.detail_url, {"username": self.barman.username, "password": "plop"}
|
self.detail_url, {"username": self.barman.username, "password": "plop"}
|
||||||
)
|
)
|
||||||
|
assert self.barman in response.wsgi_request.barmen
|
||||||
assert response.context_data.get("barmen") == [self.barman]
|
assert response.context_data.get("barmen") == [self.barman]
|
||||||
soup = BeautifulSoup(response.text, "lxml")
|
soup = BeautifulSoup(response.text, "lxml")
|
||||||
assert soup.find("form", id="select-user-form") is not None
|
assert soup.find("form", id="select-user-form") is not None
|
||||||
@@ -804,6 +804,41 @@ class TestBarmanConnection(TestCase):
|
|||||||
)
|
)
|
||||||
self.assert_counter_login_fails(self.barman)
|
self.assert_counter_login_fails(self.barman)
|
||||||
|
|
||||||
|
def test_barman_already_logged_in_another_device(self):
|
||||||
|
"""Test when the barman is already logged in the current counter on another device."""
|
||||||
|
other_client = Client()
|
||||||
|
other_client.post(
|
||||||
|
self.login_url, {"username": self.barman.username, "password": "plop"}
|
||||||
|
)
|
||||||
|
self.assert_counter_login_fails(self.barman)
|
||||||
|
|
||||||
|
def test_barman_login_elsewhere(self):
|
||||||
|
"""Test when the barman log himself out then log in on another device."""
|
||||||
|
self.client.post(
|
||||||
|
self.login_url, {"username": self.barman.username, "password": "plop"}
|
||||||
|
)
|
||||||
|
other_client = Client()
|
||||||
|
other_client.post(
|
||||||
|
reverse("counter:logout", kwargs={"counter_id": self.counter.id}),
|
||||||
|
data={"user_id": self.barman.id},
|
||||||
|
)
|
||||||
|
response = other_client.post(
|
||||||
|
self.login_url, {"username": self.barman.username, "password": "plop"}
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.headers["HX-Redirect"] == self.detail_url
|
||||||
|
# the barmen should now be logged in `other_client`...
|
||||||
|
response = other_client.get(
|
||||||
|
self.detail_url, {"username": self.barman.username, "password": "plop"}
|
||||||
|
)
|
||||||
|
assert self.barman in response.wsgi_request.barmen
|
||||||
|
|
||||||
|
# ... but not in `self.client`
|
||||||
|
response = self.client.get(
|
||||||
|
self.detail_url, {"username": self.barman.username, "password": "plop"}
|
||||||
|
)
|
||||||
|
assert self.barman not in response.wsgi_request.barmen
|
||||||
|
|
||||||
def test_barman_already_logged_elsewhere(self):
|
def test_barman_already_logged_elsewhere(self):
|
||||||
"""Test when the barman is already logged in another counter."""
|
"""Test when the barman is already logged in another counter."""
|
||||||
other_counter = baker.make(Counter, type="BAR")
|
other_counter = baker.make(Counter, type="BAR")
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ from django.views.generic.edit import FormView
|
|||||||
from core.auth.mixins import CanViewMixin
|
from core.auth.mixins import CanViewMixin
|
||||||
from core.views import FragmentMixin, UseFragmentsMixin
|
from core.views import FragmentMixin, UseFragmentsMixin
|
||||||
from counter.forms import CounterLoginForm, GetUserForm
|
from counter.forms import CounterLoginForm, GetUserForm
|
||||||
|
from counter.middleware import SESSION_PERMANENCES_KEY
|
||||||
from counter.models import Counter, Permanency
|
from counter.models import Counter, Permanency
|
||||||
from counter.utils import is_logged_in_counter
|
from counter.utils import is_logged_in_counter
|
||||||
from counter.views.mixins import CounterTabsMixin
|
from counter.views.mixins import CounterTabsMixin
|
||||||
@@ -58,8 +59,8 @@ class CounterLoginFragment(FragmentMixin, SingleObjectMixin, FormView):
|
|||||||
|
|
||||||
def form_valid(self, form: CounterLoginForm):
|
def form_valid(self, form: CounterLoginForm):
|
||||||
user = form.get_user()
|
user = form.get_user()
|
||||||
self.object.permanencies.create(user=user, start=timezone.now())
|
perm = self.object.permanencies.create(user=user, start=timezone.now())
|
||||||
self.request.barmen.add(user)
|
self.request.session.setdefault(SESSION_PERMANENCES_KEY, []).append(perm.id)
|
||||||
self.success_url = reverse(
|
self.success_url = reverse(
|
||||||
"counter:details", kwargs={"counter_id": self.object.id}
|
"counter:details", kwargs={"counter_id": self.object.id}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3217,6 +3217,10 @@ msgstr "Vous êtes déjà connecté à ce comptoir."
|
|||||||
msgid "You are already logged in another counter."
|
msgid "You are already logged in another counter."
|
||||||
msgstr "Vous êtes déjà connecté à un autre comptoir."
|
msgstr "Vous êtes déjà connecté à un autre comptoir."
|
||||||
|
|
||||||
|
#: counter/forms.py
|
||||||
|
msgid "You are already logged on another device"
|
||||||
|
msgstr "Vous êtes déjà connecté sur un autre appareil"
|
||||||
|
|
||||||
#: counter/forms.py
|
#: counter/forms.py
|
||||||
msgid "Regular barmen"
|
msgid "Regular barmen"
|
||||||
msgstr "Barmen réguliers"
|
msgstr "Barmen réguliers"
|
||||||
|
|||||||
Reference in New Issue
Block a user