""" Tests de sécurité — Settings (SMTP) Vérifie : - Le mot de passe SMTP est absent des réponses GET (write_only) - 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 Settings.models import SMTPSettings # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- def create_user_with_role(email): user = Profile.objects.create_user( username=email, email=email, password="TestPass!123" ) 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_ADMIN, 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 # --------------------------------------------------------------------------- @override_settings(**OVERRIDE) class SMTPSettingsAuthTest(TestCase): """Authentification requise sur l'endpoint SMTP.""" def setUp(self): self.client = APIClient() self.url = reverse('Settings:smtp_settings') 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 SMTPPasswordNotExposedTest(TestCase): """ Le mot de passe SMTP ne doit jamais apparaître dans les réponses GET. Avant la correction, smtp_password était retourné en clair à tout utilisateur authentifié (incluant les parents). """ def setUp(self): self.client = APIClient() self.url = reverse('Settings:smtp_settings') self.user, self.est = create_user_with_role('smtp_test@test.com') SMTPSettings.objects.create( establishment=self.est, smtp_server='smtp.example.com', smtp_port=587, smtp_user='user@example.com', smtp_password='super_secret_password_123', use_tls=True, ) def test_smtp_password_absent_de_la_reponse(self): """ GET /settings/smtp/ ne doit pas retourner smtp_password. """ token = str(RefreshToken.for_user(self.user).access_token) self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {token}') response = self.client.get(self.url, {'establishment_id': self.est.id}) self.assertEqual(response.status_code, status.HTTP_200_OK) data = response.json() # Le mot de passe ne doit pas être dans la réponse (write_only) self.assertNotIn( 'smtp_password', data, "smtp_password ne doit pas être exposé dans les réponses API (OWASP A02 - Cryptographic Failures)" ) # Vérification supplémentaire : la valeur secrète n'est pas dans la réponse brute self.assertNotIn('super_secret_password_123', response.content.decode()) def test_smtp_password_accepte_en_ecriture(self): """ POST /settings/smtp/ doit accepter smtp_password (write_only ne bloque pas l'écriture). """ token = str(RefreshToken.for_user(self.user).access_token) self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {token}') payload = { 'establishment': self.est.id, 'smtp_server': 'smtp.newserver.com', 'smtp_port': 465, 'smtp_user': 'new@example.com', 'smtp_password': 'nouveau_mot_de_passe', 'use_tls': False, 'use_ssl': True, } from rest_framework.test import APIRequestFactory response = self.client.post(self.url, data=payload, format='json') self.assertIn(response.status_code, [status.HTTP_200_OK, status.HTTP_201_CREATED])