feat: Securisation du Backend

This commit is contained in:
Luc SORIGNET
2026-02-27 10:45:36 +01:00
parent 2fef6d61a4
commit fa843097ba
55 changed files with 2898 additions and 910 deletions

View File

@ -1,3 +1,286 @@
from django.test import TestCase
"""
Tests unitaires pour le module School.
Vérifie que tous les endpoints (Speciality, Teacher, SchoolClass, Planning,
Fee, Discount, PaymentPlan, PaymentMode, Competency, EstablishmentCompetency)
requièrent une authentification JWT.
"""
# Create your tests here.
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
def create_user(email="school_test@example.com", password="testpassword123"):
return Profile.objects.create_user(username=email, email=email, password=password)
def get_jwt_token(user):
refresh = RefreshToken.for_user(user)
return str(refresh.access_token)
TEST_REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
}
TEST_CACHES = {'default': {'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}}
OVERRIDE_SETTINGS = dict(
CACHES=TEST_CACHES,
SESSION_ENGINE='django.contrib.sessions.backends.db',
REST_FRAMEWORK=TEST_REST_FRAMEWORK,
)
def _assert_endpoint_requires_auth(test_case, method, url, payload=None):
"""Utilitaire : vérifie qu'un endpoint retourne 401 sans authentification."""
client = APIClient()
call = getattr(client, method)
kwargs = {}
if payload is not None:
import json
kwargs = {"data": json.dumps(payload), "content_type": "application/json"}
response = call(url, **kwargs)
test_case.assertEqual(
response.status_code,
status.HTTP_401_UNAUTHORIZED,
msg=f"{method.upper()} {url} devrait retourner 401 sans auth, reçu {response.status_code}",
)
# ---------------------------------------------------------------------------
# Speciality
# ---------------------------------------------------------------------------
@override_settings(**OVERRIDE_SETTINGS)
class SpecialityEndpointAuthTest(TestCase):
"""Tests d'authentification sur les endpoints Speciality."""
def setUp(self):
self.client = APIClient()
self.list_url = reverse("School:speciality_list_create")
self.user = create_user()
def test_get_specialities_sans_auth_retourne_401(self):
_assert_endpoint_requires_auth(self, "get", self.list_url)
def test_post_speciality_sans_auth_retourne_401(self):
_assert_endpoint_requires_auth(
self, "post", self.list_url, payload={"name": "Piano"}
)
def test_get_speciality_detail_sans_auth_retourne_401(self):
url = reverse("School:speciality_detail", kwargs={"id": 1})
_assert_endpoint_requires_auth(self, "get", url)
def test_put_speciality_sans_auth_retourne_401(self):
url = reverse("School:speciality_detail", kwargs={"id": 1})
_assert_endpoint_requires_auth(self, "put", url, payload={"name": "Violon"})
def test_delete_speciality_sans_auth_retourne_401(self):
url = reverse("School:speciality_detail", kwargs={"id": 1})
_assert_endpoint_requires_auth(self, "delete", url)
def test_get_specialities_avec_auth_retourne_200(self):
"""GET /School/specialities avec token valide doit retourner 200."""
token = get_jwt_token(self.user)
self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {token}")
response = self.client.get(self.list_url, {"establishment_id": 1})
self.assertIn(response.status_code, [status.HTTP_200_OK, status.HTTP_400_BAD_REQUEST])
# ---------------------------------------------------------------------------
# Teacher
# ---------------------------------------------------------------------------
@override_settings(**OVERRIDE_SETTINGS)
class TeacherEndpointAuthTest(TestCase):
"""Tests d'authentification sur les endpoints Teacher."""
def setUp(self):
self.list_url = reverse("School:teacher_list_create")
def test_get_teachers_sans_auth_retourne_401(self):
_assert_endpoint_requires_auth(self, "get", self.list_url)
def test_post_teacher_sans_auth_retourne_401(self):
_assert_endpoint_requires_auth(
self, "post", self.list_url, payload={"first_name": "Jean"}
)
def test_get_teacher_detail_sans_auth_retourne_401(self):
url = reverse("School:teacher_detail", kwargs={"id": 1})
_assert_endpoint_requires_auth(self, "get", url)
def test_put_teacher_sans_auth_retourne_401(self):
url = reverse("School:teacher_detail", kwargs={"id": 1})
_assert_endpoint_requires_auth(self, "put", url, payload={"first_name": "Pierre"})
def test_delete_teacher_sans_auth_retourne_401(self):
url = reverse("School:teacher_detail", kwargs={"id": 1})
_assert_endpoint_requires_auth(self, "delete", url)
# ---------------------------------------------------------------------------
# SchoolClass
# ---------------------------------------------------------------------------
@override_settings(**OVERRIDE_SETTINGS)
class SchoolClassEndpointAuthTest(TestCase):
"""Tests d'authentification sur les endpoints SchoolClass."""
def setUp(self):
self.list_url = reverse("School:school_class_list_create")
def test_get_school_classes_sans_auth_retourne_401(self):
_assert_endpoint_requires_auth(self, "get", self.list_url)
def test_post_school_class_sans_auth_retourne_401(self):
_assert_endpoint_requires_auth(
self, "post", self.list_url, payload={"name": "Classe A"}
)
def test_get_school_class_detail_sans_auth_retourne_401(self):
url = reverse("School:school_class_detail", kwargs={"id": 1})
_assert_endpoint_requires_auth(self, "get", url)
# ---------------------------------------------------------------------------
# Fee
# ---------------------------------------------------------------------------
@override_settings(**OVERRIDE_SETTINGS)
class FeeEndpointAuthTest(TestCase):
"""Tests d'authentification sur les endpoints Fee."""
def setUp(self):
self.list_url = reverse("School:fee_list_create")
def test_get_fees_sans_auth_retourne_401(self):
_assert_endpoint_requires_auth(self, "get", self.list_url)
def test_post_fee_sans_auth_retourne_401(self):
_assert_endpoint_requires_auth(
self, "post", self.list_url, payload={"amount": 100}
)
def test_get_fee_detail_sans_auth_retourne_401(self):
url = reverse("School:fee_detail", kwargs={"id": 1})
_assert_endpoint_requires_auth(self, "get", url)
def test_put_fee_sans_auth_retourne_401(self):
url = reverse("School:fee_detail", kwargs={"id": 1})
_assert_endpoint_requires_auth(self, "put", url, payload={"amount": 200})
def test_delete_fee_sans_auth_retourne_401(self):
url = reverse("School:fee_detail", kwargs={"id": 1})
_assert_endpoint_requires_auth(self, "delete", url)
# ---------------------------------------------------------------------------
# Discount
# ---------------------------------------------------------------------------
@override_settings(**OVERRIDE_SETTINGS)
class DiscountEndpointAuthTest(TestCase):
"""Tests d'authentification sur les endpoints Discount."""
def setUp(self):
self.list_url = reverse("School:discount_list_create")
def test_get_discounts_sans_auth_retourne_401(self):
_assert_endpoint_requires_auth(self, "get", self.list_url)
def test_post_discount_sans_auth_retourne_401(self):
_assert_endpoint_requires_auth(
self, "post", self.list_url, payload={"rate": 10}
)
# ---------------------------------------------------------------------------
# PaymentPlan
# ---------------------------------------------------------------------------
@override_settings(**OVERRIDE_SETTINGS)
class PaymentPlanEndpointAuthTest(TestCase):
"""Tests d'authentification sur les endpoints PaymentPlan."""
def setUp(self):
self.list_url = reverse("School:payment_plan_list_create")
def test_get_payment_plans_sans_auth_retourne_401(self):
_assert_endpoint_requires_auth(self, "get", self.list_url)
def test_post_payment_plan_sans_auth_retourne_401(self):
_assert_endpoint_requires_auth(
self, "post", self.list_url, payload={"name": "Plan A"}
)
# ---------------------------------------------------------------------------
# PaymentMode
# ---------------------------------------------------------------------------
@override_settings(**OVERRIDE_SETTINGS)
class PaymentModeEndpointAuthTest(TestCase):
"""Tests d'authentification sur les endpoints PaymentMode."""
def setUp(self):
self.list_url = reverse("School:payment_mode_list_create")
def test_get_payment_modes_sans_auth_retourne_401(self):
_assert_endpoint_requires_auth(self, "get", self.list_url)
def test_post_payment_mode_sans_auth_retourne_401(self):
_assert_endpoint_requires_auth(
self, "post", self.list_url, payload={"name": "Virement"}
)
# ---------------------------------------------------------------------------
# Competency
# ---------------------------------------------------------------------------
@override_settings(**OVERRIDE_SETTINGS)
class CompetencyEndpointAuthTest(TestCase):
"""Tests d'authentification sur les endpoints Competency."""
def setUp(self):
self.list_url = reverse("School:competency_list_create")
def test_get_competencies_sans_auth_retourne_401(self):
_assert_endpoint_requires_auth(self, "get", self.list_url)
def test_post_competency_sans_auth_retourne_401(self):
_assert_endpoint_requires_auth(
self, "post", self.list_url, payload={"name": "Lecture"}
)
# ---------------------------------------------------------------------------
# EstablishmentCompetency
# ---------------------------------------------------------------------------
@override_settings(**OVERRIDE_SETTINGS)
class EstablishmentCompetencyEndpointAuthTest(TestCase):
"""Tests d'authentification sur les endpoints EstablishmentCompetency."""
def setUp(self):
self.list_url = reverse("School:establishment_competency_list_create")
def test_get_establishment_competencies_sans_auth_retourne_401(self):
_assert_endpoint_requires_auth(self, "get", self.list_url)
def test_post_establishment_competency_sans_auth_retourne_401(self):
_assert_endpoint_requires_auth(
self, "post", self.list_url, payload={"competency": 1}
)