05eeb6a25c
Refer to allauth doc for an accurate features list: http://django-allauth.readthedocs.io/en/latest/ Users can now change their password, ask for a password reset, or set one if they don't have one. In particular, it allows users whose account has been created via a clipper authentication to configure a password before losing their clipper. Even if they have already lost it, they are able to get one using the "Reset password" functionality. Allauth multiple emails management is deactivated. Requests to the related url redirect to the home page. All the login and logout views are replaced by the allauth' ones. It also concerns the Django and Wagtail admin sites. Note that users are no longer logged out of the clipper CAS server when they authenticated via this server. Instead a message suggests the user to disconnect. Clipper connections and `login_clipper` --------------------------------------- - Non-empty `login_clipper` are now unique among `CofProfile` instances. - They are created once for users with a non-empty 'login_clipper' (with the data migration 0014_create_clipper_connections). - The `login_clipper` of CofProfile instances are sync with their clipper connections: * `CofProfile.sync_clipper_connections` method updates the connections based on `login_clipper`. * Signals receivers `sync_clipper…` update `login_clipper` based on connections creations/updates/deletions. Misc ---- - Add NullCharField (model field) which allows to use `unique=True` on CharField (even with empty strings). - Parts of kfet mixins for TestCase are now in shared.tests.testcase, as they are used elsewhere than in the kfet app.
238 lines
7.8 KiB
Python
238 lines
7.8 KiB
Python
import json
|
|
import os
|
|
from datetime import timedelta
|
|
from unittest import mock
|
|
from urllib.parse import urlencode
|
|
|
|
from django.conf import settings
|
|
from django.contrib.auth.models import User
|
|
from django.core.management import call_command
|
|
from django.test import Client, TestCase
|
|
from django.urls import reverse
|
|
from django.utils import timezone
|
|
|
|
from ..models import CategorieSpectacle, Salle, Spectacle, Tirage
|
|
|
|
|
|
def create_user(username, is_cof=False, is_buro=False):
|
|
user = User.objects.create_user(username=username, password=username)
|
|
user.profile.is_cof = is_cof
|
|
user.profile.is_buro = is_buro
|
|
user.profile.save()
|
|
return user
|
|
|
|
|
|
def user_is_cof(user):
|
|
return (user is not None) and user.profile.is_cof
|
|
|
|
|
|
def user_is_staff(user):
|
|
return (user is not None) and user.profile.is_buro
|
|
|
|
|
|
class BdATestHelpers:
|
|
def setUp(self):
|
|
# Some user with different access privileges
|
|
staff = create_user(username="bda_staff", is_cof=True, is_buro=True)
|
|
staff_c = Client()
|
|
staff_c.force_login(staff)
|
|
|
|
member = create_user(username="bda_member", is_cof=True)
|
|
member_c = Client()
|
|
member_c.force_login(member)
|
|
|
|
other = create_user(username="bda_other")
|
|
other_c = Client()
|
|
other_c.force_login(other)
|
|
|
|
self.client_matrix = [
|
|
(staff, staff_c),
|
|
(member, member_c),
|
|
(other, other_c),
|
|
(None, Client()),
|
|
]
|
|
|
|
def require_custommails(self):
|
|
data_file = os.path.join(
|
|
settings.BASE_DIR, "gestioncof", "management", "data", "custommail.json"
|
|
)
|
|
call_command("syncmails", data_file, verbosity=0)
|
|
|
|
def check_restricted_access(
|
|
self, url, validate_user=user_is_cof, redirect_url=None
|
|
):
|
|
def craft_redirect_url(user):
|
|
if redirect_url:
|
|
return redirect_url
|
|
login_url = reverse("account_login")
|
|
if url:
|
|
login_url += "?{}".format(urlencode({"next": url}, safe="/"))
|
|
return login_url
|
|
|
|
for (user, client) in self.client_matrix:
|
|
resp = client.get(url, follow=True)
|
|
if validate_user(user):
|
|
self.assertEqual(200, resp.status_code)
|
|
else:
|
|
self.assertRedirects(resp, craft_redirect_url(user))
|
|
|
|
|
|
class TestBdAViews(BdATestHelpers, TestCase):
|
|
def setUp(self):
|
|
# Set up the helpers
|
|
super().setUp()
|
|
# Some BdA stuff
|
|
self.tirage = Tirage.objects.create(
|
|
title="Test tirage",
|
|
appear_catalogue=True,
|
|
ouverture=timezone.now(),
|
|
fermeture=timezone.now(),
|
|
)
|
|
self.category = CategorieSpectacle.objects.create(name="Category")
|
|
self.location = Salle.objects.create(name="here")
|
|
Spectacle.objects.bulk_create(
|
|
[
|
|
Spectacle(
|
|
title="foo",
|
|
date=timezone.now(),
|
|
location=self.location,
|
|
price=0,
|
|
slots=42,
|
|
tirage=self.tirage,
|
|
listing=False,
|
|
category=self.category,
|
|
),
|
|
Spectacle(
|
|
title="bar",
|
|
date=timezone.now(),
|
|
location=self.location,
|
|
price=1,
|
|
slots=142,
|
|
tirage=self.tirage,
|
|
listing=False,
|
|
category=self.category,
|
|
),
|
|
Spectacle(
|
|
title="baz",
|
|
date=timezone.now(),
|
|
location=self.location,
|
|
price=2,
|
|
slots=242,
|
|
tirage=self.tirage,
|
|
listing=False,
|
|
category=self.category,
|
|
),
|
|
]
|
|
)
|
|
|
|
def test_bda_inscriptions(self):
|
|
# TODO: test the form
|
|
url = "/bda/inscription/{}".format(self.tirage.id)
|
|
self.check_restricted_access(url)
|
|
|
|
def test_bda_places(self):
|
|
url = "/bda/places/{}".format(self.tirage.id)
|
|
self.check_restricted_access(url)
|
|
|
|
def test_etat_places(self):
|
|
url = "/bda/etat-places/{}".format(self.tirage.id)
|
|
self.check_restricted_access(url)
|
|
|
|
def test_perform_tirage(self):
|
|
# Only staff member can perform a tirage
|
|
url = "/bda/tirage/{}".format(self.tirage.id)
|
|
self.check_restricted_access(url, validate_user=user_is_staff)
|
|
|
|
_, staff_c = self.client_matrix[0]
|
|
# Cannot be performed if disabled
|
|
self.tirage.enable_do_tirage = False
|
|
self.tirage.save()
|
|
resp = staff_c.get(url)
|
|
self.assertTemplateUsed(resp, "tirage-failed.html")
|
|
# Cannot be performed if registrations are still open
|
|
self.tirage.enable_do_tirage = True
|
|
self.tirage.fermeture = timezone.now() + timedelta(seconds=3600)
|
|
self.tirage.save()
|
|
resp = staff_c.get(url)
|
|
self.assertTemplateUsed(resp, "tirage-failed.html")
|
|
# Otherwise, perform the tirage
|
|
self.tirage.fermeture = timezone.now()
|
|
self.tirage.save()
|
|
resp = staff_c.get(url)
|
|
self.assertTemplateNotUsed(resp, "tirage-failed.html")
|
|
|
|
def test_spectacles_list(self):
|
|
url = "/bda/spectacles/{}".format(self.tirage.id)
|
|
self.check_restricted_access(url, validate_user=user_is_staff)
|
|
|
|
def test_spectacle_detail(self):
|
|
show = self.tirage.spectacle_set.first()
|
|
url = "/bda/spectacles/{}/{}".format(self.tirage.id, show.id)
|
|
self.check_restricted_access(url, validate_user=user_is_staff)
|
|
|
|
def test_tirage_unpaid(self):
|
|
url = "/bda/spectacles/unpaid/{}".format(self.tirage.id)
|
|
self.check_restricted_access(url, validate_user=user_is_staff)
|
|
|
|
def test_send_reminders(self):
|
|
self.require_custommails()
|
|
# Just get the page
|
|
show = self.tirage.spectacle_set.first()
|
|
url = "/bda/mails-rappel/{}".format(show.id)
|
|
self.check_restricted_access(url, validate_user=user_is_staff)
|
|
# Actually send the reminder emails
|
|
_, staff_c = self.client_matrix[0]
|
|
resp = staff_c.post(url)
|
|
self.assertEqual(200, resp.status_code)
|
|
# TODO: check that emails are sent
|
|
|
|
def test_catalogue_api(self):
|
|
url_list = "/bda/catalogue/list"
|
|
url_details = "/bda/catalogue/details?id={}".format(self.tirage.id)
|
|
url_descriptions = "/bda/catalogue/descriptions?id={}".format(self.tirage.id)
|
|
|
|
# Anyone can get
|
|
def anyone_can_get(url):
|
|
self.check_restricted_access(url, validate_user=lambda user: True)
|
|
|
|
anyone_can_get(url_list)
|
|
anyone_can_get(url_details)
|
|
anyone_can_get(url_descriptions)
|
|
|
|
# The resulting JSON contains the information
|
|
_, client = self.client_matrix[0]
|
|
|
|
# List
|
|
resp = client.get(url_list)
|
|
self.assertJSONEqual(
|
|
resp.content.decode("utf-8"),
|
|
[{"id": self.tirage.id, "title": self.tirage.title}],
|
|
)
|
|
|
|
# Details
|
|
resp = client.get(url_details)
|
|
self.assertJSONEqual(
|
|
resp.content.decode("utf-8"),
|
|
{
|
|
"categories": [{"id": self.category.id, "name": self.category.name}],
|
|
"locations": [{"id": self.location.id, "name": self.location.name}],
|
|
},
|
|
)
|
|
|
|
# Descriptions
|
|
resp = client.get(url_descriptions)
|
|
raw = resp.content.decode("utf-8")
|
|
try:
|
|
results = json.loads(raw)
|
|
except ValueError:
|
|
self.fail("Not valid JSON: {}".format(raw))
|
|
self.assertEqual(len(results), 3)
|
|
self.assertEqual(
|
|
{(s["title"], s["price"], s["slots"]) for s in results},
|
|
{("foo", 0, 42), ("bar", 1, 142), ("baz", 2, 242)},
|
|
)
|
|
|
|
|
|
class TestBdaRevente:
|
|
pass
|
|
# TODO
|