mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-10-31 07:49:57 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			453 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			453 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
 | |
| # SPDX-License-Identifier: GPL-3.0-or-later
 | |
| 
 | |
| import hashlib
 | |
| import os
 | |
| from datetime import date, timedelta
 | |
| 
 | |
| from api.tests import TestAPI
 | |
| from django.contrib.auth.models import User
 | |
| from django.core.files.uploadedfile import SimpleUploadedFile
 | |
| from django.db.models import Q
 | |
| from django.test import TestCase
 | |
| from django.urls import reverse
 | |
| from django.utils import timezone
 | |
| from note.models import Alias, NoteSpecial
 | |
| from permission.models import Role
 | |
| from treasury.models import SogeCredit
 | |
| 
 | |
| from ..api.views import ClubViewSet, MembershipViewSet, ProfileViewSet
 | |
| from ..models import Club, Membership, Profile
 | |
| 
 | |
| """
 | |
| Create some users and clubs and test that all pages are rendering properly
 | |
| and that memberships are working.
 | |
| """
 | |
| 
 | |
| 
 | |
| class TestMemberships(TestCase):
 | |
|     fixtures = ('initial', )
 | |
| 
 | |
|     def setUp(self) -> None:
 | |
|         """
 | |
|         Create a sample superuser, a club and a membership for all tests.
 | |
|         """
 | |
|         self.user = User.objects.create_superuser(
 | |
|             username="toto",
 | |
|             email="toto@example.com",
 | |
|             password="toto",
 | |
|         )
 | |
|         self.user.profile.registration_valid = True
 | |
|         self.user.profile.email_confirmed = True
 | |
|         self.user.profile.save()
 | |
|         self.client.force_login(self.user)
 | |
| 
 | |
|         sess = self.client.session
 | |
|         sess["permission_mask"] = 42
 | |
|         sess.save()
 | |
| 
 | |
|         self.club = Club.objects.create(name="totoclub", parent_club=Club.objects.get(name="BDE"))
 | |
|         self.bde_membership = Membership.objects.create(user=self.user, club=Club.objects.get(name="BDE"))
 | |
|         self.membership = Membership.objects.create(user=self.user, club=self.club)
 | |
|         self.membership.roles.add(Role.objects.get(name="Bureau de club"))
 | |
|         self.membership.save()
 | |
| 
 | |
|     def test_admin_pages(self):
 | |
|         """
 | |
|         Check that Django Admin pages for the member app are loading successfully.
 | |
|         """
 | |
|         response = self.client.get(reverse("admin:index") + "member/membership/")
 | |
|         self.assertEqual(response.status_code, 200)
 | |
|         response = self.client.get(reverse("admin:index") + "member/club/")
 | |
|         self.assertEqual(response.status_code, 200)
 | |
|         response = self.client.get(reverse("admin:index") + "auth/user/")
 | |
|         self.assertEqual(response.status_code, 200)
 | |
|         response = self.client.get(reverse("admin:index") + "auth/user/" + str(self.user.pk) + "/change/")
 | |
|         self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|     def test_render_club_list(self):
 | |
|         """
 | |
|         Render the list of all clubs, with a search.
 | |
|         """
 | |
|         response = self.client.get(reverse("member:club_list"))
 | |
|         self.assertEqual(response.status_code, 200)
 | |
|         response = self.client.get(reverse("member:club_list") + "?search=toto")
 | |
|         self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|     def test_render_club_create(self):
 | |
|         """
 | |
|         Try to create a new club.
 | |
|         """
 | |
|         response = self.client.get(reverse("member:club_create"))
 | |
|         self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|         response = self.client.post(reverse("member:club_create"), data=dict(
 | |
|             name="Club toto",
 | |
|             email="clubtoto@example.com",
 | |
|             parent_club=self.club.pk,
 | |
|             require_memberships=False,
 | |
|             membership_fee_paid=0,
 | |
|             membership_fee_unpaid=0,
 | |
|         ))
 | |
|         self.assertTrue(Club.objects.filter(name="Club toto").exists())
 | |
|         club = Club.objects.get(name="Club toto")
 | |
|         self.assertRedirects(response, club.get_absolute_url(), 302, 200)
 | |
| 
 | |
|     def test_render_club_detail(self):
 | |
|         """
 | |
|         Display the detail of a club.
 | |
|         """
 | |
|         response = self.client.get(reverse("member:club_detail", args=(self.club.pk,)))
 | |
|         self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|     def test_render_club_update(self):
 | |
|         """
 | |
|         Try to update the information about a club.
 | |
|         """
 | |
|         response = self.client.get(reverse("member:club_update", args=(self.club.pk,)))
 | |
|         self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|         response = self.client.post(reverse("member:club_update", args=(self.club.pk, )), data=dict(
 | |
|             name="Toto club updated",
 | |
|             email="clubtoto@example.com",
 | |
|             require_memberships=True,
 | |
|             membership_fee_paid=0,
 | |
|             membership_fee_unpaid=0,
 | |
|         ))
 | |
|         self.assertRedirects(response, self.club.get_absolute_url(), 302, 200)
 | |
|         self.assertTrue(Club.objects.exclude(name="Toto club updated"))
 | |
| 
 | |
|     def test_render_club_update_picture(self):
 | |
|         """
 | |
|         Try to update the picture of the note of a club.
 | |
|         """
 | |
|         response = self.client.get(reverse("member:club_update_pic", args=(self.club.pk,)))
 | |
|         self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|         old_pic = self.club.note.display_image
 | |
| 
 | |
|         with open("apps/member/static/member/img/default_picture.png", "rb") as f:
 | |
|             image = SimpleUploadedFile("image.png", f.read(), "image/png")
 | |
|             response = self.client.post(reverse("member:club_update_pic", args=(self.club.pk,)), dict(
 | |
|                 image=image,
 | |
|                 x=0,
 | |
|                 y=0,
 | |
|                 width=200,
 | |
|                 height=200,
 | |
|             ))
 | |
|             self.assertRedirects(response, self.club.get_absolute_url(), 302, 200)
 | |
| 
 | |
|         self.club.note.refresh_from_db()
 | |
|         self.assertTrue(os.path.exists(self.club.note.display_image.path))
 | |
|         os.remove(self.club.note.display_image.path)
 | |
| 
 | |
|         self.club.note.display_image = old_pic
 | |
|         self.club.note.save()
 | |
| 
 | |
|     def test_render_club_aliases(self):
 | |
|         """
 | |
|         Display the list of the aliases of a club.
 | |
|         """
 | |
|         # Alias creation and deletion is already tested in the note app
 | |
|         response = self.client.get(reverse("member:club_alias", args=(self.club.pk,)))
 | |
|         self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|     def test_render_club_members(self):
 | |
|         """
 | |
|         Display the list of the members of a club.
 | |
|         """
 | |
|         response = self.client.get(reverse("member:club_members", args=(self.club.pk,)))
 | |
|         self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|         response = self.client.get(reverse("member:club_members", args=(self.club.pk,)) + "?search=toto&roles="
 | |
|                                    + ",".join([str(role.pk) for role in
 | |
|                                                Role.objects.filter(weirole__isnull=True).all()]))
 | |
|         self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|     def test_render_club_add_member(self):
 | |
|         """
 | |
|         Try to add memberships and renew them.
 | |
|         """
 | |
|         response = self.client.get(reverse("member:club_add_member", args=(Club.objects.get(name="BDE").pk,)))
 | |
|         self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|         user = User.objects.create(username="totototo")
 | |
|         user.profile.registration_valid = True
 | |
|         user.profile.email_confirmed = True
 | |
|         user.profile.save()
 | |
|         user.save()
 | |
| 
 | |
|         # We create a club without any parent and one club with parent BDE (that is the club Kfet)
 | |
|         for bde_parent in False, True:
 | |
|             if bde_parent:
 | |
|                 club = Club.objects.get(name="Kfet")
 | |
|             else:
 | |
|                 club = Club.objects.create(
 | |
|                     name="Second club without BDE",
 | |
|                     parent_club=None,
 | |
|                     email="newclub@example.com",
 | |
|                     require_memberships=True,
 | |
|                     membership_fee_paid=1000,
 | |
|                     membership_fee_unpaid=500,
 | |
|                     membership_start=date.today(),
 | |
|                     membership_end=date.today() + timedelta(days=366),
 | |
|                     membership_duration=366,
 | |
|                 )
 | |
| 
 | |
|             response = self.client.get(reverse("member:club_add_member", args=(club.pk,)))
 | |
|             self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|             # Create a new membership
 | |
|             response = self.client.post(reverse("member:club_add_member", args=(club.pk,)), data=dict(
 | |
|                 user=user.pk,
 | |
|                 date_start="{:%Y-%m-%d}".format(date.today()),
 | |
|                 soge=False,
 | |
|                 credit_type=NoteSpecial.objects.get(special_type="Espèces").id,
 | |
|                 credit_amount=4200,
 | |
|                 last_name="TOTO",
 | |
|                 first_name="Toto",
 | |
|                 bank="Le matelas",
 | |
|             ))
 | |
|             self.assertRedirects(response, user.profile.get_absolute_url(), 302, 200)
 | |
| 
 | |
|             self.assertTrue(Membership.objects.filter(user=user, club=club).exists())
 | |
| 
 | |
|             # Membership is sent to the past to check renewals
 | |
|             membership = Membership.objects.get(user=user, club=club)
 | |
|             self.assertTrue(membership.valid)
 | |
|             membership.date_start = date(year=2000, month=1, day=1)
 | |
|             membership.date_end = date(year=2000, month=12, day=31)
 | |
|             membership.save()
 | |
|             self.assertFalse(membership.valid)
 | |
| 
 | |
|             response = self.client.get(reverse("member:club_members", args=(club.pk,)) + "?only_active=0")
 | |
|             self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|             bde_membership = self.bde_membership
 | |
|             if bde_parent:
 | |
|                 bde_membership = Membership.objects.get(club__name="BDE", user=user)
 | |
|                 bde_membership.date_start = date(year=2000, month=1, day=1)
 | |
|                 bde_membership.date_end = date(year=2000, month=12, day=31)
 | |
|                 bde_membership.save()
 | |
| 
 | |
|             response = self.client.get(reverse("member:club_renew_membership", args=(bde_membership.pk,)))
 | |
|             self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|             response = self.client.get(reverse("member:club_renew_membership", args=(membership.pk,)))
 | |
|             self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|             # Renew membership
 | |
|             response = self.client.post(reverse("member:club_renew_membership", args=(membership.pk,)), data=dict(
 | |
|                 user=user.pk,
 | |
|                 date_start="{:%Y-%m-%d}".format(date.today()),
 | |
|                 soge=bde_parent,
 | |
|                 credit_type=NoteSpecial.objects.get(special_type="Chèque").id,
 | |
|                 credit_amount=14242,
 | |
|                 last_name="TOTO",
 | |
|                 first_name="Toto",
 | |
|                 bank="Bank",
 | |
|             ))
 | |
|             self.assertRedirects(response, user.profile.get_absolute_url(), 302, 200)
 | |
| 
 | |
|             response = self.client.get(club.get_absolute_url())
 | |
|             self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|     def test_auto_join_kfet_when_join_bde_with_soge(self):
 | |
|         """
 | |
|         When we join the BDE club with a Soge registration, a Kfet membership is automatically created.
 | |
|         We check that it is the case.
 | |
|         """
 | |
|         user = User.objects.create(username="new1A")
 | |
|         user.profile.registration_valid = True
 | |
|         user.profile.email_confirmed = True
 | |
|         user.profile.save()
 | |
|         user.save()
 | |
| 
 | |
|         bde = Club.objects.get(name="BDE")
 | |
|         kfet = Club.objects.get(name="Kfet")
 | |
| 
 | |
|         response = self.client.post(reverse("member:club_add_member", args=(bde.pk,)), data=dict(
 | |
|             user=user.pk,
 | |
|             date_start="{:%Y-%m-%d}".format(date.today()),
 | |
|             soge=True,
 | |
|             credit_type=NoteSpecial.objects.get(special_type="Virement bancaire").id,
 | |
|             credit_amount=(bde.membership_fee_paid + kfet.membership_fee_paid) / 100,
 | |
|             last_name="TOTO",
 | |
|             first_name="Toto",
 | |
|             bank="Société générale",
 | |
|         ))
 | |
|         self.assertRedirects(response, user.profile.get_absolute_url(), 302, 200)
 | |
| 
 | |
|         self.assertTrue(Membership.objects.filter(user=user, club=bde).exists())
 | |
|         self.assertTrue(Membership.objects.filter(user=user, club=kfet).exists())
 | |
|         self.assertTrue(SogeCredit.objects.filter(user=user).exists())
 | |
| 
 | |
|     def test_change_roles(self):
 | |
|         """
 | |
|         Check to change the roles of a membership.
 | |
|         """
 | |
|         response = self.client.get(reverse("member:club_manage_roles", args=(self.membership.pk,)))
 | |
|         self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|         response = self.client.post(reverse("member:club_manage_roles", args=(self.membership.pk,)), data=dict(
 | |
|             roles=[role.id for role in Role.objects.filter(
 | |
|                 Q(name="Membre de club") | Q(name="Trésorièr⋅e de club") | Q(name="Bureau de club")).all()],
 | |
|         ))
 | |
|         self.assertRedirects(response, self.user.profile.get_absolute_url(), 302, 200)
 | |
|         self.membership.refresh_from_db()
 | |
|         self.assertEqual(self.membership.roles.count(), 3)
 | |
| 
 | |
|     def test_render_user_list(self):
 | |
|         """
 | |
|         Display the user search page.
 | |
|         """
 | |
|         response = self.client.get(reverse("member:user_list"))
 | |
|         self.assertEqual(response.status_code, 200)
 | |
|         response = self.client.get(reverse("member:user_list") + "?search=toto")
 | |
|         self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|     def test_render_user_detail(self):
 | |
|         """
 | |
|         Display the user detail page.
 | |
|         """
 | |
|         response = self.client.get(self.user.profile.get_absolute_url())
 | |
|         self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|     def test_render_user_update(self):
 | |
|         """
 | |
|         Update some data about the user.
 | |
|         """
 | |
|         response = self.client.get(reverse("member:user_update_profile", args=(self.user.pk,)))
 | |
|         self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|         response = self.client.post(reverse("member:user_update_profile", args=(self.user.pk,)), data=dict(
 | |
|             first_name="Toto",
 | |
|             last_name="Toto",
 | |
|             username="toto changed",
 | |
|             email="updated@example.com",
 | |
|             phone_number="+33600000000",
 | |
|             section="",
 | |
|             department="A0",
 | |
|             promotion=timezone.now().year,
 | |
|             address="Earth",
 | |
|             paid=True,
 | |
|             ml_events_registration="en",
 | |
|             ml_sports_registration=True,
 | |
|             ml_art_registration=True,
 | |
|             report_frequency=7,
 | |
|             VSS_charter_read=True
 | |
|         ))
 | |
|         self.assertRedirects(response, self.user.profile.get_absolute_url(), 302, 200)
 | |
|         self.assertTrue(User.objects.filter(username="toto changed").exists())
 | |
|         self.assertTrue(Profile.objects.filter(address="Earth").exists())
 | |
|         self.assertTrue(Alias.objects.filter(normalized_name="totochanged").exists())
 | |
| 
 | |
|     def test_render_user_update_picture(self):
 | |
|         """
 | |
|         Update the note picture of the user.
 | |
|         """
 | |
|         response = self.client.get(reverse("member:user_update_pic", args=(self.user.pk,)))
 | |
|         self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|         old_pic = self.user.note.display_image
 | |
| 
 | |
|         with open("apps/member/static/member/img/default_picture.png", "rb") as f:
 | |
|             image = SimpleUploadedFile("image.png", f.read(), "image/png")
 | |
|             response = self.client.post(reverse("member:user_update_pic", args=(self.user.pk,)), dict(
 | |
|                 image=image,
 | |
|                 x=0,
 | |
|                 y=0,
 | |
|                 width=200,
 | |
|                 height=200,
 | |
|             ))
 | |
|             self.assertRedirects(response, self.user.profile.get_absolute_url(), 302, 200)
 | |
| 
 | |
|         self.user.note.refresh_from_db()
 | |
|         self.assertTrue(os.path.exists(self.user.note.display_image.path))
 | |
|         os.remove(self.user.note.display_image.path)
 | |
| 
 | |
|         self.user.note.display_image = old_pic
 | |
|         self.user.note.save()
 | |
| 
 | |
|     def test_render_user_aliases(self):
 | |
|         """
 | |
|         Display the list of aliases of the user.
 | |
|         """
 | |
|         # Alias creation and deletion is already tested in the note app
 | |
|         response = self.client.get(reverse("member:user_alias", args=(self.user.pk,)))
 | |
|         self.assertEqual(response.status_code, 200)
 | |
| 
 | |
|     def test_manage_auth_token(self):
 | |
|         """
 | |
|         Display the page to see the API authentication token, see it and regenerate it.
 | |
|         :return:
 | |
|         """
 | |
|         response = self.client.get(reverse("member:auth_token"))
 | |
|         self.assertEqual(response.status_code, 200)
 | |
|         response = self.client.get(reverse("member:auth_token") + "?view")
 | |
|         self.assertEqual(response.status_code, 200)
 | |
|         response = self.client.get(reverse("member:auth_token") + "?regenerate")
 | |
|         self.assertRedirects(response, reverse("member:auth_token") + "?view", 302, 200)
 | |
| 
 | |
|     def test_random_coverage(self):
 | |
|         # Useless, only for coverage
 | |
|         self.assertEqual(str(self.user), str(self.user.profile))
 | |
|         self.user.profile.promotion = None
 | |
|         self.assertEqual(self.user.profile.ens_year, 0)
 | |
|         self.membership.date_end = None
 | |
|         self.assertTrue(self.membership.valid)
 | |
| 
 | |
|     def test_nk15_hasher(self):
 | |
|         """
 | |
|         Test that NK15 passwords are successfully imported.
 | |
|         """
 | |
|         salt = "42"
 | |
|         password = "strongpassword42"
 | |
|         hashed = hashlib.sha256((salt + password).encode("utf-8")).hexdigest()
 | |
|         self.user.password = "custom_nk15$1$" + salt + "|" + hashed
 | |
|         self.user.save()
 | |
|         self.assertTrue(self.user.check_password(password))
 | |
| 
 | |
| 
 | |
| class TestMemberAPI(TestAPI):
 | |
|     def setUp(self) -> None:
 | |
|         super().setUp()
 | |
| 
 | |
|         self.user.profile.registration_valid = True
 | |
|         self.user.profile.email_confirmed = True
 | |
|         self.user.profile.phone_number = "0600000000"
 | |
|         self.user.profile.section = "1A0"
 | |
|         self.user.profile.department = "A0"
 | |
|         self.user.profile.address = "Earth"
 | |
|         self.user.profile.save()
 | |
| 
 | |
|         self.club = Club.objects.create(
 | |
|             name="totoclub",
 | |
|             parent_club=Club.objects.get(name="BDE"),
 | |
|             membership_start=date(year=1970, month=1, day=1),
 | |
|             membership_end=date(year=2040, month=1, day=1),
 | |
|             membership_duration=365 * 10,
 | |
|         )
 | |
|         self.bde_membership = Membership.objects.create(user=self.user, club=Club.objects.get(name="BDE"))
 | |
|         self.membership = Membership.objects.create(user=self.user, club=self.club)
 | |
|         self.membership.roles.add(Role.objects.get(name="Bureau de club"))
 | |
|         self.membership.save()
 | |
| 
 | |
|     def test_club_api(self):
 | |
|         """
 | |
|         Load Club API page and test all filters and permissions
 | |
|         """
 | |
|         self.check_viewset(ClubViewSet, "/api/members/club/")
 | |
| 
 | |
|     def test_profile_api(self):
 | |
|         """
 | |
|         Load Profile API page and test all filters and permissions
 | |
|         """
 | |
|         self.check_viewset(ProfileViewSet, "/api/members/profile/")
 | |
| 
 | |
|     def test_membership_api(self):
 | |
|         """
 | |
|         Load Membership API page and test all filters and permissions
 | |
|         """
 | |
|         self.check_viewset(MembershipViewSet, "/api/members/membership/")
 |