""" Tests de sécurité — GestionEmail Vérifie : - search_recipients nécessite une authentification (plus accessible anonymement) - send-email nécessite une authentification - Les données personnelles ne sont pas dans les logs INFO """ import json from django.test import TestCase, override_settings from django.urls import reverse from rest_framework import status from rest_framework.test import APIClient from rest_framework_simplejwt.tokens import RefreshToken from Auth.models import Profile, ProfileRole from Establishment.models import Establishment # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- def create_user_with_role(email, password="TestPass!123"): user = Profile.objects.create_user( username=email, email=email, password=password ) est = Establishment.objects.create( name=f"Ecole {email}", address="1 rue Test", total_capacity=50, establishment_type=[1], ) ProfileRole.objects.create( profile=user, role_type=ProfileRole.RoleType.PROFIL_ECOLE, establishment=est, is_active=True, ) return user, est OVERRIDE = dict( CACHES={'default': {'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}}, SESSION_ENGINE='django.contrib.sessions.backends.db', ) # --------------------------------------------------------------------------- # Tests : search_recipients exige une authentification # --------------------------------------------------------------------------- @override_settings(**OVERRIDE) class SearchRecipientsAuthTest(TestCase): """ GET /email/search-recipients/ doit retourner 401 si non authentifié. Avant la correction, cet endpoint était accessible anonymement (harvesting d'emails des membres d'un établissement). """ def setUp(self): self.client = APIClient() self.url = reverse('GestionEmail:search_recipients') def test_sans_auth_retourne_401(self): """Accès anonyme doit être rejeté avec 401.""" response = self.client.get(self.url, {'q': 'test', 'establishment_id': 1}) self.assertEqual( response.status_code, status.HTTP_401_UNAUTHORIZED, "search_recipients doit exiger une authentification (OWASP A01 - Broken Access Control)" ) def test_avec_auth_et_query_vide_retourne_200_ou_liste_vide(self): """Un utilisateur authentifié sans terme de recherche reçoit une liste vide.""" user, est = create_user_with_role('search_auth@test.com') token = str(RefreshToken.for_user(user).access_token) self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {token}') response = self.client.get(self.url, {'q': '', 'establishment_id': est.id}) self.assertIn(response.status_code, [status.HTTP_200_OK, status.HTTP_400_BAD_REQUEST]) def test_avec_auth_et_establishment_manquant_retourne_400(self): """Un utilisateur authentifié sans establishment_id reçoit 400.""" user, _ = create_user_with_role('search_noest@test.com') token = str(RefreshToken.for_user(user).access_token) self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {token}') response = self.client.get(self.url, {'q': 'alice'}) self.assertIn(response.status_code, [status.HTTP_400_BAD_REQUEST, status.HTTP_200_OK]) # --------------------------------------------------------------------------- # Tests : send-email exige une authentification # --------------------------------------------------------------------------- @override_settings(**OVERRIDE) class SendEmailAuthTest(TestCase): """ POST /email/send-email/ doit retourner 401 si non authentifié. """ def setUp(self): self.client = APIClient() self.url = reverse('GestionEmail:send_email') def test_sans_auth_retourne_401(self): """Accès anonyme à l'envoi d'email doit être rejeté.""" payload = { 'recipients': ['victim@example.com'], 'subject': 'Test', 'message': 'Hello', 'establishment_id': 1, } response = self.client.post( self.url, data=json.dumps(payload), content_type='application/json' ) self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)