feat: make student card unique per user

This commit is contained in:
imperosol
2024-12-08 16:07:25 +01:00
committed by Sli
parent 3b7e338808
commit 466fe58763
13 changed files with 250 additions and 426 deletions

View File

@ -1,3 +1,4 @@
import itertools
import json
import string
from datetime import timedelta
@ -175,7 +176,6 @@ class TestStudentCard(TestCase):
@classmethod
def setUpTestData(cls):
cls.customer = subscriber_user.make()
cls.customer.save()
cls.barmen = subscriber_user.make(password=make_password("plop"))
cls.board_admin = board_user.make()
cls.club_admin = baker.make(User)
@ -205,6 +205,22 @@ class TestStudentCard(TestCase):
{"username": self.barmen.username, "password": "plop"},
)
def invalid_uids(self) -> list[tuple[str, str]]:
"""Return a list of invalid uids, with the associated error message"""
return [
("8B90734A802A8", ""), # too short
(
"8B90734A802A8FA",
"Assurez-vous que cette valeur comporte au plus 14 caractères (actuellement 15).",
), # too long
("8b90734a802a9f", ""), # has lowercases
(" " * 14, "Ce champ est obligatoire."), # empty
(
self.customer.customer.student_card.uid,
"Un objet Carte étudiante avec ce champ Uid existe déjà.",
),
]
def test_search_user_with_student_card(self):
response = self.client.post(
reverse("counter:details", args=[self.counter.id]),
@ -213,396 +229,144 @@ class TestStudentCard(TestCase):
assert response.url == reverse(
"counter:click",
kwargs={"counter_id": self.counter.id, "user_id": self.customer.id},
kwargs={"counter_id": self.counter.id, "user_id": self.customer.pk},
)
def test_add_student_card_from_counter(self):
# Test card with mixed letters and numbers
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={
"customer_id": self.customer.customer.pk,
},
),
{"uid": "8B90734A802A8F"},
HTTP_REFERER=reverse(
"counter:click",
kwargs={
"counter_id": self.counter.id,
"user_id": self.customer.customer.pk,
},
),
)
assert response.status_code == 302
self.assertContains(self.client.get(response.url), text="8B90734A802A8F")
# Test card with only numbers
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={
"customer_id": self.customer.customer.pk,
},
),
{"uid": "04786547890123"},
HTTP_REFERER=reverse(
"counter:click",
kwargs={
"counter_id": self.counter.id,
"user_id": self.customer.customer.pk,
},
),
)
assert response.status_code == 302
self.assertContains(self.client.get(response.url), text="04786547890123")
# Test card with only letters
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={
"customer_id": self.customer.customer.pk,
},
),
{"uid": "ABCAAAFAAFAAAB"},
HTTP_REFERER=reverse(
"counter:click",
kwargs={
"counter_id": self.counter.id,
"user_id": self.customer.customer.pk,
},
),
)
assert response.status_code == 302
self.assertContains(self.client.get(response.url), text="ABCAAAFAAFAAAB")
for uid in ["8B90734A802A8F", "ABCAAAFAAFAAAB", "15248196326518"]:
customer = subscriber_user.make().customer
response = self.client.post(
reverse(
"counter:add_student_card", kwargs={"customer_id": customer.pk}
),
{"uid": uid},
HTTP_REFERER=reverse(
"counter:click",
kwargs={"counter_id": self.counter.id, "user_id": customer.pk},
),
)
assert response.status_code == 302
customer.refresh_from_db()
assert hasattr(customer, "student_card")
assert customer.student_card.uid == uid
def test_add_student_card_from_counter_fail(self):
# UID too short
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={
"customer_id": self.customer.customer.pk,
},
),
{"uid": "8B90734A802A8"},
HTTP_REFERER=reverse(
"counter:click",
kwargs={
"counter_id": self.counter.id,
"user_id": self.customer.customer.pk,
},
),
)
self.assertContains(response, text="Cet UID est invalide")
# UID too long
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={
"customer_id": self.customer.customer.pk,
},
),
{"uid": "8B90734A802A8FA"},
HTTP_REFERER=reverse(
"counter:click",
kwargs={
"counter_id": self.counter.id,
"user_id": self.customer.customer.pk,
},
),
)
self.assertContains(response, text="Cet UID est invalide")
self.assertContains(
response,
text="Assurez-vous que cette valeur comporte au plus 14 caractères (actuellement 15).",
)
# Test with already existing card
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={
"customer_id": self.customer.customer.pk,
},
),
{"uid": self.valid_card.uid},
HTTP_REFERER=reverse(
"counter:click",
kwargs={
"counter_id": self.counter.id,
"user_id": self.customer.customer.pk,
},
),
)
self.assertContains(response, text="Cet UID est invalide")
self.assertContains(
response, text="Un objet Student card avec ce champ Uid existe déjà."
)
# Test with lowercase
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={
"customer_id": self.customer.customer.pk,
},
),
{"uid": "8b90734a802a9f"},
HTTP_REFERER=reverse(
"counter:click",
kwargs={
"counter_id": self.counter.id,
"user_id": self.customer.customer.pk,
},
),
)
self.assertContains(response, text="Cet UID est invalide")
# Test with white spaces
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={
"customer_id": self.customer.customer.pk,
},
),
{"uid": " "},
HTTP_REFERER=reverse(
"counter:click",
kwargs={
"counter_id": self.counter.id,
"user_id": self.customer.customer.pk,
},
),
)
self.assertContains(response, text="Cet UID est invalide")
self.assertContains(response, text="Ce champ est obligatoire.")
customer = subscriber_user.make().customer
for uid, error_msg in self.invalid_uids():
response = self.client.post(
reverse(
"counter:add_student_card", kwargs={"customer_id": customer.pk}
),
{"uid": uid},
HTTP_REFERER=reverse(
"counter:click",
kwargs={"counter_id": self.counter.id, "user_id": customer.pk},
),
)
self.assertContains(response, text="Cet UID est invalide")
self.assertContains(response, text=error_msg)
customer.refresh_from_db()
assert not hasattr(customer, "student_card")
def test_add_student_card_from_counter_unauthorized(self):
# Send to a counter where you aren't logged in
self.client.post(
reverse("counter:logout", args=[self.counter.id]),
{"user_id": self.barmen.id},
)
barman = subscriber_user.make()
self.counter.sellers.add(barman)
customer = self.customer.customer
# There is someone logged to a counter
# with the client of this TestCase instance,
# so we create a new client, in order to check
# that using a client not logged to a counter
# where another client is logged still isn't authorized.
client = Client()
def send_valid_request(client, counter_id):
def send_valid_request(counter_id):
return client.post(
reverse(
"counter:add_student_card",
kwargs={
"customer_id": self.customer.customer.pk,
},
"counter:add_student_card", kwargs={"customer_id": customer.pk}
),
{"uid": "8B90734A802A8F"},
HTTP_REFERER=reverse(
"counter:click",
kwargs={
"counter_id": counter_id,
"user_id": self.customer.customer.pk,
},
kwargs={"counter_id": counter_id, "user_id": customer.pk},
),
)
assert send_valid_request(self.client, self.counter.id).status_code == 403
# Send to a counter where you aren't logged in
assert send_valid_request(self.counter.id).status_code == 403
# Send to a non bar counter
self.client.force_login(self.club_admin)
assert send_valid_request(self.client, self.club_counter.id).status_code == 403
client.force_login(self.club_admin)
assert send_valid_request(self.club_counter.id).status_code == 403
def test_delete_student_card_with_owner(self):
self.client.force_login(self.customer)
self.client.post(
reverse(
"counter:delete_student_card",
kwargs={
"customer_id": self.customer.customer.pk,
"card_id": self.customer.customer.student_cards.first().id,
},
kwargs={"customer_id": self.customer.customer.pk},
)
)
assert not self.customer.customer.student_cards.exists()
self.customer.customer.refresh_from_db()
assert not hasattr(self.customer.customer, "student_card")
def test_delete_student_card_with_board_member(self):
self.client.force_login(self.board_admin)
self.client.post(
reverse(
"counter:delete_student_card",
kwargs={
"customer_id": self.customer.customer.pk,
"card_id": self.customer.customer.student_cards.first().id,
},
def test_delete_student_card_with_admin_user(self):
"""Test that AE board members and root users can delete student cards"""
for user in self.board_admin, self.root:
self.client.force_login(user)
self.client.post(
reverse(
"counter:delete_student_card",
kwargs={"customer_id": self.customer.customer.pk},
)
)
)
assert not self.customer.customer.student_cards.exists()
def test_delete_student_card_with_root(self):
self.client.force_login(self.root)
self.client.post(
reverse(
"counter:delete_student_card",
kwargs={
"customer_id": self.customer.customer.pk,
"card_id": self.customer.customer.student_cards.first().id,
},
)
)
assert not self.customer.customer.student_cards.exists()
self.customer.customer.refresh_from_db()
assert not hasattr(self.customer.customer, "student_card")
def test_delete_student_card_fail(self):
"""Test that non-admin users cannot delete student cards"""
self.client.force_login(self.subscriber)
response = self.client.post(
reverse(
"counter:delete_student_card",
kwargs={
"customer_id": self.customer.customer.pk,
"card_id": self.customer.customer.student_cards.first().id,
},
kwargs={"customer_id": self.customer.customer.pk},
)
)
assert response.status_code == 403
assert self.customer.customer.student_cards.exists()
self.subscriber.customer.refresh_from_db()
assert not hasattr(self.subscriber.customer, "student_card")
def test_add_student_card_from_user_preferences(self):
# Test with owner of the card
self.client.force_login(self.customer)
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={"customer_id": self.customer.customer.pk},
),
{"uid": "8B90734A802A8F"},
)
users = [self.subscriber, self.board_admin, self.root]
uids = ["8B90734A802A8F", "ABCAAAFAAFAAAB", "15248196326518"]
for user, uid in itertools.product(users, uids):
self.customer.customer.student_card.delete()
self.client.force_login(user)
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={"customer_id": self.customer.customer.pk},
),
{"uid": uid},
)
assert response.status_code == 302
response = self.client.get(response.url)
assert response.status_code == 302
response = self.client.get(response.url)
self.assertContains(response, text="8B90734A802A8F")
# Test with board member
self.client.force_login(self.board_admin)
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={"customer_id": self.customer.customer.pk},
),
{"uid": "8B90734A802A8A"},
)
assert response.status_code == 302
response = self.client.get(response.url)
self.assertContains(response, text="8B90734A802A8A")
# Test card with only numbers
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={"customer_id": self.customer.customer.pk},
),
{"uid": "04786547890123"},
)
assert response.status_code == 302
response = self.client.get(response.url)
self.assertContains(response, text="04786547890123")
# Test card with only letters
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={"customer_id": self.customer.customer.pk},
),
{"uid": "ABCAAAFAAFAAAB"},
)
assert response.status_code == 302
response = self.client.get(response.url)
self.assertContains(response, text="ABCAAAFAAFAAAB")
# Test with root
self.client.force_login(self.root)
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={"customer_id": self.customer.customer.pk},
),
{"uid": "8B90734A802A8B"},
)
assert response.status_code == 302
response = self.client.get(response.url)
self.assertContains(response, text="8B90734A802A8B")
self.customer.customer.refresh_from_db()
assert self.customer.customer.student_card.uid == uid
self.assertContains(response, text="Enregistré")
def test_add_student_card_from_user_preferences_fail(self):
self.client.force_login(self.customer)
# UID too short
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={"customer_id": self.customer.customer.pk},
),
{"uid": "8B90734A802A8"},
)
self.assertContains(response, text="Cet UID est invalide")
# UID too long
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={"customer_id": self.customer.customer.pk},
),
{"uid": "8B90734A802A8FA"},
)
self.assertContains(response, text="Cet UID est invalide")
# Test with already existing card
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={"customer_id": self.customer.customer.pk},
),
{"uid": self.valid_card.uid},
)
self.assertContains(
response, text="Un objet Student card avec ce champ Uid existe déjà."
)
# Test with lowercase
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={"customer_id": self.customer.customer.pk},
),
{"uid": "8b90734a802a9f"},
)
self.assertContains(response, text="Cet UID est invalide")
# Test with white spaces
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={"customer_id": self.customer.customer.pk},
),
{"uid": " " * 14},
)
self.assertContains(response, text="Cet UID est invalide")
# Test with unauthorized user
self.client.force_login(self.subscriber)
response = self.client.post(
reverse(
"counter:add_student_card",
kwargs={"customer_id": self.customer.customer.pk},
),
{"uid": "8B90734A802A8F"},
)
assert response.status_code == 403
customer = subscriber_user.make()
self.client.force_login(customer)
for uid, error_msg in self.invalid_uids():
url = reverse(
"counter:add_student_card", kwargs={"customer_id": customer.customer.pk}
)
response = self.client.post(url, {"uid": uid})
self.assertContains(response, text="Cet UID est invalide")
self.assertContains(response, text=error_msg)
customer.refresh_from_db()
assert not hasattr(customer.customer, "student_card")
class TestCustomerAccountId(TestCase):