""" Tests de sécurité — GestionNotification Vérifie : - Les notifications sont filtrées par utilisateur (plus d'accès global) - Authentification requise """ 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 from GestionNotification.models import Notification # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- def create_user_with_role(email, name="Ecole Test"): user = Profile.objects.create_user( username=email, email=email, password="TestPass!123" ) est = Establishment.objects.create( name=name, 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 OVERRIDE = dict( CACHES={'default': {'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}}, SESSION_ENGINE='django.contrib.sessions.backends.db', ) # --------------------------------------------------------------------------- # Tests # --------------------------------------------------------------------------- @override_settings(**OVERRIDE) class NotificationAuthTest(TestCase): """Authentification requise sur l'endpoint notifications.""" def setUp(self): self.client = APIClient() self.url = reverse('GestionNotification:notifications') def test_sans_auth_retourne_401(self): response = self.client.get(self.url) self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) @override_settings(**OVERRIDE) class NotificationFilterTest(TestCase): """ Chaque utilisateur ne voit que ses propres notifications. Avant la correction, toutes les notifications étaient retournées à n'importe quel utilisateur authentifié (IDOR). """ def setUp(self): self.client = APIClient() self.url = reverse('GestionNotification:notifications') self.alice = create_user_with_role('alice_notif@test.com', 'Ecole Alice') self.bob = create_user_with_role('bob_notif@test.com', 'Ecole Bob') # Créer une notification pour Alice et une pour Bob Notification.objects.create( user=self.alice, message='Message pour Alice', typeNotification=0 ) Notification.objects.create( user=self.bob, message='Message pour Bob', typeNotification=0 ) def test_alice_voit_uniquement_ses_notifications(self): """Alice ne doit voir que sa propre notification, pas celle de Bob.""" token = str(RefreshToken.for_user(self.alice).access_token) self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {token}') response = self.client.get(self.url) self.assertEqual(response.status_code, status.HTTP_200_OK) data = response.json() self.assertEqual(len(data), 1, "Alice doit voir uniquement ses propres notifications") self.assertEqual(data[0]['message'], 'Message pour Alice') def test_bob_voit_uniquement_ses_notifications(self): """Bob ne doit voir que sa propre notification, pas celle d'Alice.""" token = str(RefreshToken.for_user(self.bob).access_token) self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {token}') response = self.client.get(self.url) self.assertEqual(response.status_code, status.HTTP_200_OK) data = response.json() self.assertEqual(len(data), 1, "Bob doit voir uniquement ses propres notifications") self.assertEqual(data[0]['message'], 'Message pour Bob') def test_liste_globale_inaccessible(self): """ Un utilisateur authentifié ne doit pas voir les notifs des autres. Vérification croisée : nombre de notifs retournées == 1. """ carol = create_user_with_role('carol_notif@test.com', 'Ecole Carol') token = str(RefreshToken.for_user(carol).access_token) self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {token}') response = self.client.get(self.url) self.assertEqual(response.status_code, status.HTTP_200_OK) data = response.json() # Carol n'a aucune notification self.assertEqual(len(data), 0, "Un utilisateur sans notification ne doit pas voir celles des autres (IDOR)")