# Copyright (C) 2020 by Animath # SPDX-License-Identifier: GPL-3.0-or-later from datetime import timedelta import os from django.conf import settings from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType from django.contrib.sites.models import Site from django.core.files.uploadedfile import SimpleUploadedFile from django.test import override_settings, TestCase from django.urls import reverse from django.utils import timezone from django.utils.encoding import force_bytes from django.utils.http import urlsafe_base64_encode from participation.models import Team from tfjm.tokens import email_validation_token from .models import CoachRegistration, StudentRegistration, VolunteerRegistration class TestIndexPage(TestCase): def test_index(self) -> None: """ Display the index page, without any right. """ response = self.client.get(reverse("index")) self.assertEqual(response.status_code, 200) def test_not_authenticated(self): """ Try to load some pages without being authenticated. """ response = self.client.get(reverse("registration:reset_admin")) self.assertRedirects(response, reverse("login") + "?next=" + reverse("registration:reset_admin"), 302, 200) User.objects.create() response = self.client.get(reverse("registration:user_detail", args=(1,))) self.assertRedirects(response, reverse("login") + "?next=" + reverse("registration:user_detail", args=(1,))) Team.objects.create() response = self.client.get(reverse("participation:team_detail", args=(1,))) self.assertRedirects(response, reverse("login") + "?next=" + reverse("participation:team_detail", args=(1,))) response = self.client.get(reverse("participation:update_team", args=(1,))) self.assertRedirects(response, reverse("login") + "?next=" + reverse("participation:update_team", args=(1,))) response = self.client.get(reverse("participation:create_team")) self.assertRedirects(response, reverse("login") + "?next=" + reverse("participation:create_team")) response = self.client.get(reverse("participation:join_team")) self.assertRedirects(response, reverse("login") + "?next=" + reverse("participation:join_team")) response = self.client.get(reverse("participation:team_authorizations", args=(1,))) self.assertRedirects(response, reverse("login") + "?next=" + reverse("participation:team_authorizations", args=(1,))) response = self.client.get(reverse("participation:participation_detail", args=(1,))) self.assertRedirects(response, reverse("login") + "?next=" + reverse("participation:participation_detail", args=(1,))) class TestRegistration(TestCase): def setUp(self) -> None: self.user = User.objects.create_superuser( username="admin", password="admin", email="admin@example.com", ) self.client.force_login(self.user) self.student = User.objects.create(email="student@example.com") StudentRegistration.objects.create( user=self.student, student_class=11, school="Earth", address="1 Rue de Rivoli", zip_code=75001, city="Paris", ) self.coach = User.objects.create(email="coach@example.com") CoachRegistration.objects.create( user=self.coach, address="1 Rue de Rivoli", zip_code=75001, city="Paris", professional_activity="Teacher", ) def test_admin_pages(self): """ Check that admin pages are rendering successfully. """ response = self.client.get(reverse("admin:index") + "registration/registration/") self.assertEqual(response.status_code, 200) response = self.client.get(reverse("admin:index") + f"registration/registration/{self.user.registration.pk}/change/") self.assertEqual(response.status_code, 200) response = self.client.get(reverse("admin:index") + f"r/{ContentType.objects.get_for_model(VolunteerRegistration).id}/" f"{self.user.registration.pk}/") self.assertRedirects(response, "http://" + Site.objects.get().domain + str(self.user.registration.get_absolute_url()), 302, 200) response = self.client.get(reverse("admin:index") + f"registration/registration/{self.student.registration.pk}/change/") self.assertEqual(response.status_code, 200) response = self.client.get(reverse("admin:index") + f"r/{ContentType.objects.get_for_model(StudentRegistration).id}/" f"{self.student.registration.pk}/") self.assertRedirects(response, "http://" + Site.objects.get().domain + str(self.student.registration.get_absolute_url()), 302, 200) response = self.client.get(reverse("admin:index") + f"registration/registration/{self.coach.registration.pk}/change/") self.assertEqual(response.status_code, 200) response = self.client.get(reverse("admin:index") + f"r/{ContentType.objects.get_for_model(CoachRegistration).id}/" f"{self.coach.registration.pk}/") self.assertRedirects(response, "http://" + Site.objects.get().domain + str(self.coach.registration.get_absolute_url()), 302, 200) # Ensure that we are between registration dates @override_settings(REGISTRATION_DATES={'open': timezone.now() - timedelta(days=1), 'close': timezone.now() + timedelta(days=1)}) def test_registration(self): """ Ensure that the signup form is working successfully. """ response = self.client.get(reverse("registration:signup")) self.assertEqual(response.status_code, 200) # Incomplete form response = self.client.post(reverse("registration:signup"), data=dict( last_name="Toto", first_name="Toto", email="toto@example.com", password1="azertyuiopazertyuiop", password2="azertyuiopazertyuiop", role="participant", )) self.assertEqual(response.status_code, 200) response = self.client.post(reverse("registration:signup"), data=dict( last_name="Toto", first_name="Toto", email="toto@example.com", password1="azertyuiopazertyuiop", password2="azertyuiopazertyuiop", role="participant", student_class=12, school="God", birth_date="2000-01-01", gender="other", address="1 Rue de Rivoli", zip_code=75001, city="Paris", country="France", phone_number="0123456789", responsible_name="Toto", responsible_phone="0123456789", responsible_email="toto@example.com", give_contact_to_animath=False, )) self.assertRedirects(response, reverse("registration:email_validation_sent"), 302, 200) self.assertTrue(User.objects.filter( email="toto@example.com", registration__participantregistration__studentregistration__responsible_name="Toto").exists()) # Email is already used response = self.client.post(reverse("registration:signup"), data=dict( last_name="Toto", first_name="Toto", email="toto@example.com", password1="azertyuiopazertyuiop", password2="azertyuiopazertyuiop", role="participant", student_class=12, school="God", birth_date="2000-01-01", gender="other", address="1 Rue de Rivoli", zip_code=75001, city="Paris", phone_number="0123456789", responsible_name="Toto", responsible_phone="0123456789", responsible_email="toto@example.com", give_contact_to_animath=False, )) self.assertEqual(response.status_code, 200) response = self.client.get(reverse("registration:email_validation_sent")) self.assertEqual(response.status_code, 200) response = self.client.post(reverse("registration:signup"), data=dict( last_name="Toto", first_name="Coach", email="coachtoto@example.com", password1="azertyuiopazertyuiop", password2="azertyuiopazertyuiop", role="coach", gender="other", address="1 Rue de Rivoli", zip_code=75001, city="Paris", country="France", phone_number="0123456789", professional_activity="God", last_degree="Master", give_contact_to_animath=True, )) self.assertRedirects(response, reverse("registration:email_validation_sent"), 302, 200) self.assertTrue(User.objects.filter(email="coachtoto@example.com").exists()) user = User.objects.get(email="coachtoto@example.com") token = email_validation_token.make_token(user) uid = urlsafe_base64_encode(force_bytes(user.pk)) response = self.client.get(reverse("registration:email_validation", kwargs=dict(uidb64=uid, token=token))) self.assertEqual(response.status_code, 200) user.registration.refresh_from_db() self.assertTrue(user.registration.email_confirmed) # Token has expired response = self.client.get(reverse("registration:email_validation", kwargs=dict(uidb64=uid, token=token))) self.assertEqual(response.status_code, 400) # Uid does not exist response = self.client.get(reverse("registration:email_validation", kwargs=dict(uidb64=0, token="toto"))) self.assertEqual(response.status_code, 400) response = self.client.get(reverse("registration:email_validation_resend", args=(user.pk,))) self.assertRedirects(response, reverse("registration:email_validation_sent"), 302, 200) def test_registration_dates(self): """ Test that registrations are working only between registration dates. """ self.client.logout() # Test that registration between open and close dates are working with override_settings(REGISTRATION_DATES={'open': timezone.now() - timedelta(days=2), 'close': timezone.now() + timedelta(days=2)}): response = self.client.get(reverse("registration:signup")) self.assertEqual(response.status_code, 200) self.assertIn(" Register", response.content.decode()) self.assertNotIn("registrations are not opened", response.content.decode()) self.assertNotIn("Registrations are closed", response.content.decode()) response = self.client.post(reverse("registration:signup")) self.assertFormError(response.context['form'], None, []) # Test that registration before open date is not working with override_settings(REGISTRATION_DATES={'open': timezone.now() + timedelta(days=1), 'close': timezone.now() + timedelta(days=2)}): response = self.client.get(reverse("registration:signup")) self.assertEqual(response.status_code, 200) self.assertNotIn(" Register", response.content.decode()) self.assertIn("registrations are not opened", response.content.decode()) response = self.client.post(reverse("registration:signup")) self.assertEqual(response.status_code, 200) self.assertFormError(response.context['form'], None, "Registrations are not opened yet. They will open on the " f"{settings.REGISTRATION_DATES['open']:%Y-%m-%d %H:%M}.") # Test that registration after close date is not working with override_settings(REGISTRATION_DATES={'open': timezone.now() - timedelta(days=2), 'close': timezone.now() - timedelta(days=1)}): response = self.client.get(reverse("registration:signup")) self.assertEqual(response.status_code, 200) self.assertNotIn(" Register", response.content.decode()) self.assertIn("Registrations are closed", response.content.decode()) response = self.client.post(reverse("registration:signup")) self.assertEqual(response.status_code, 200) self.assertFormError(response.context['form'], None, "Registrations for this year are closed since " f"{settings.REGISTRATION_DATES['close']:%Y-%m-%d %H:%M}.") def test_login(self): """ With a registered user, try to log in """ response = self.client.get(reverse("login")) self.assertEqual(response.status_code, 200) self.client.logout() response = self.client.post(reverse("login"), data=dict( username="admin", password="toto", )) self.assertEqual(response.status_code, 200) response = self.client.post(reverse("login"), data=dict( username="admin@example.com", password="admin", )) self.assertRedirects(response, reverse("index"), 302, 200) def test_user_detail(self): """ Load a user detail page. """ response = self.client.get(reverse("registration:my_account_detail")) self.assertRedirects(response, reverse("registration:user_detail", args=(self.user.pk,))) response = self.client.get(reverse("registration:user_detail", args=(self.user.pk,))) self.assertEqual(response.status_code, 200) def test_user_list(self): """ Display the list of all users. """ response = self.client.get(reverse("registration:user_list")) self.assertEqual(response.status_code, 200) def test_update_user(self): """ Update the user information, for each type of user. """ # To test the modification of mailing lists from participation.models import Team self.student.registration.team = Team.objects.create( name="toto", trigram="TOT", ) self.student.registration.save() for user, data in [(self.user, dict(professional_activity="Bot", admin=True)), (self.student, dict(student_class=11, school="Sky", birth_date="2001-01-01", gender="female", address="1 Rue de Rivoli", zip_code=75001, city="Paris", country="France", responsible_name="Toto", responsible_phone="0123456789", responsible_email="toto@example.com")), (self.coach, dict(professional_activity="God", last_degree="Médaille Fields", gender="male", address="1 Rue de Rivoli", zip_code=75001, city="Paris", country="France"))]: response = self.client.get(reverse("registration:update_user", args=(user.pk,))) self.assertEqual(response.status_code, 200) response = self.client.post(reverse("registration:update_user", args=(user.pk,)), data=dict( first_name="Changed", last_name="Name", email="new_" + user.email, give_contact_to_animath=True, email_confirmed=True, team_id="", )) self.assertEqual(response.status_code, 200) data.update( first_name="Changed", last_name="Name", email="new_" + user.email, give_contact_to_animath=True, email_confirmed=True, team_id="", ) response = self.client.post(reverse("registration:update_user", args=(user.pk,)), data=data) self.assertRedirects(response, reverse("registration:user_detail", args=(user.pk,)), 302, 200) user.refresh_from_db() self.assertEqual(user.email, user.username) self.assertFalse(user.registration.email_confirmed) self.assertEqual(user.first_name, "Changed") def test_upload_photo_authorization(self): """ Try to upload a photo authorization. """ for auth_type in ["photo_authorization", "health_sheet", "parental_authorization"]: response = self.client.get(reverse("registration:upload_user_photo_authorization", args=(self.student.registration.pk,))) self.assertEqual(response.status_code, 200) # README is not a valid PDF file response = self.client.post(reverse(f"registration:upload_user_{auth_type}", args=(self.student.registration.pk,)), data={ auth_type: open("README.md", "rb"), }) self.assertEqual(response.status_code, 200) # Don't send too large files response = self.client.post(reverse(f"registration:upload_user_{auth_type}", args=(self.student.registration.pk,)), data={ auth_type: SimpleUploadedFile("file.pdf", content=int(0).to_bytes(2000001, "big"), content_type="application/pdf"), }) self.assertEqual(response.status_code, 200) response = self.client.post(reverse(f"registration:upload_user_{auth_type}", args=(self.student.registration.pk,)), data={ auth_type: open("tfjm/static/tfjm/Fiche_sanitaire.pdf", "rb"), }) self.assertRedirects(response, reverse("registration:user_detail", args=(self.student.pk,)), 302, 200) self.student.registration.refresh_from_db() self.assertTrue(getattr(self.student.registration, auth_type)) response = self.client.get(reverse( auth_type, args=(getattr(self.student.registration, auth_type).name.split('/')[-1],))) self.assertEqual(response.status_code, 200) from participation.models import Team team = Team.objects.create(name="Test", trigram="TES") self.student.registration.team = team self.student.registration.save() response = self.client.get(reverse("participation:team_authorizations", args=(team.pk,))) self.assertEqual(response.status_code, 200) self.assertEqual(response["content-type"], "application/zip") # Do it twice, ensure that the previous authorization got deleted old_authoratization = self.student.registration.photo_authorization.path response = self.client.post(reverse("registration:upload_user_photo_authorization", args=(self.student.registration.pk,)), data=dict( photo_authorization=open("tfjm/static/tfjm/Fiche_sanitaire.pdf", "rb"), )) self.assertRedirects(response, reverse("registration:user_detail", args=(self.student.pk,)), 302, 200) self.assertFalse(os.path.isfile(old_authoratization)) self.student.registration.refresh_from_db() self.student.registration.photo_authorization.delete() self.student.registration.save() def test_user_detail_forbidden(self): """ Create a new user and ensure that it can't see the detail of another user. """ self.client.force_login(self.coach) response = self.client.get(reverse("registration:user_detail", args=(self.user.pk,))) self.assertEqual(response.status_code, 403) response = self.client.get(reverse("registration:update_user", args=(self.user.pk,))) self.assertEqual(response.status_code, 403) response = self.client.get(reverse("registration:upload_user_photo_authorization", args=(self.student.registration.pk,))) self.assertEqual(response.status_code, 403) response = self.client.get(reverse("photo_authorization", args=("inexisting-authorization",))) self.assertEqual(response.status_code, 404) with open("media/authorization/photo/example", "w") as f: f.write("I lost the game.") self.student.registration.photo_authorization = "authorization/photo/example" self.student.registration.save() response = self.client.get(reverse("photo_authorization", args=("example",))) self.assertEqual(response.status_code, 403) os.remove("media/authorization/photo/example") def test_impersonate(self): """ Admin can impersonate other people to act as them. """ response = self.client.get(reverse("registration:user_impersonate", args=(0x7ffff42ff,))) self.assertEqual(response.status_code, 404) # Impersonate student account response = self.client.get(reverse("registration:user_impersonate", args=(self.student.pk,))) self.assertRedirects(response, reverse("registration:user_detail", args=(self.student.pk,)), 302, 200) self.assertEqual(self.client.session["_fake_user_id"], self.student.id) # Reset admin view response = self.client.get(reverse("registration:reset_admin")) self.assertRedirects(response, reverse("index"), 302, 200) self.assertFalse("_fake_user_id" in self.client.session) def test_research(self): """ Try to search some things. """ response = self.client.get(reverse("haystack_search") + "?q=" + self.user.email + "&models=auth.user") self.assertEqual(response.status_code, 200) self.assertTrue(response.context["object_list"]) response = self.client.get(reverse("haystack_search") + "?q=" + str(self.coach.registration.professional_activity) + "&models=registration.CoachRegistration") self.assertEqual(response.status_code, 200) self.assertTrue(response.context["object_list"]) response = self.client.get(reverse("haystack_search") + "?q=" + self.student.registration.school + "&models=registration.StudentRegistration") self.assertEqual(response.status_code, 200) self.assertTrue(response.context["object_list"])