Aller au contenu principal

Permissions & Contrôle d'Accès

Ce document décrit le système de permissions de StageConnect : les rôles utilisateurs, les droits associés, et comment ils sont appliqués dans le backend.

Rôles Utilisateurs (UserType)

Le backend définit 6 rôles dans l'enum UserType (app/core/config.py). Ces rôles sont encodés dans chaque JWT dans le claim user_type.

Rôle JWTCodeInterfaceRôle métier
STUDENTUserType.STUDENTDiscover ou CareerÉtudiant L1/L2 ou L3/M
UNIVERSITY_ADMINUserType.UNIVERSITY_ADMINCareerResponsable pédagogique université
ACADEMIC_SUPERVISORUserType.ACADEMIC_SUPERVISORCareer (portail encadrant)Encadreur académique
COMPANYUserType.COMPANYCareerReprésentant entreprise
COMPANY_MENTORUserType.COMPANY_MENTORCareer (portail encadrant)Maître de stage
PLATFORM_ADMINUserType.PLATFORM_ADMINAdminAdministrateur plateforme
Distinction DB vs JWT

Dans la base de données (users.user_type), les valeurs sont différentes : STUDENT, ACADEMIC_STAFF, COMPANY_STAFF, ADMIN, SCHOOL_STAFF. Ces valeurs DB sont ensuite mappées vers les rôles JWT lors de l'authentification. Dans le code Python, toujours utiliser UserType.UNIVERSITY_ADMIN etc., pas les valeurs brutes de la DB.

Dépendances FastAPI par Rôle

Le fichier app/utils/dependencies.py expose des dépendances prêtes à l'emploi :

# Accès étudiant uniquement
current_user = Depends(get_current_student)

# Accès admin université uniquement
current_user = Depends(get_current_university_admin)

# Accès encadreur académique uniquement
current_user = Depends(get_current_academic_supervisor)

# Accès entreprise uniquement
current_user = Depends(get_current_company_user)

# Accès maître de stage uniquement
current_user = Depends(get_current_company_mentor)

# Accès admin plateforme uniquement
current_user = Depends(get_current_platform_admin)

Multi-rôles

# Utiliser require_user_types() pour les endpoints multi-rôles
from app.utils.dependencies import require_user_types
from app.core.config import UserType

@router.get("/shared-endpoint")
async def shared_endpoint(
current_user = Depends(require_user_types([
UserType.UNIVERSITY_ADMIN,
UserType.PLATFORM_ADMIN
]))
):
...

Matrice des Droits par Rôle

Étudiants

ActionL1/L2 (Discover)L3/M (Career)
Voir les offres de stage (liste)
Voir le détail d'une offre
Candidater à une offre
Retirer une candidature
Modifier son profil (basique)
Uploader un CV
Proposer un thème de stage
Créer un binôme
Consulter sa convention
Soumettre un rapport
Niveau L1/L2 vs L3/M

La séparation L1/L2 vs L3/M est actuellement gérée côté frontend par l'application (Discover vs Career). Le backend applique les permissions par UserType.STUDENT sans distinction de niveau. La distinction de niveau académique est basée sur students.academic_year en DB et vérifiée dans les services métier concernés.

Université

ActionUNIVERSITY_ADMIN
Voir les étudiants de son université
Valider les thèmes de stage
Assigner des encadreurs académiques
Gérer les conventions de stage
Programmer les soutenances
Voir les statistiques université
Accéder aux données d'autres universités

Entreprise

ActionCOMPANYCOMPANY_MENTOR
Publier des offres
Voir les candidatures reçues
Voir les stagiaires en cours✅ (siens uniquement)
Évaluer un stagiaire
Gérer les maîtres de stage
Voir le profil des candidats

Admin Plateforme

ActionPLATFORM_ADMIN
Lire toutes les données
Modifier les utilisateurs
Voir les logs d'activité
Gérer les plans tarifaires
Accéder aux rapports de bugs
Suspendre un compte

Décorateurs de Sécurité

Le fichier app/utils/decorators.py fournit des décorateurs pour vérifications rapides :

from app.utils.decorators import require_platform_admin, require_university_admin, require_company_access

@router.delete("/users/{user_id}")
@require_platform_admin
async def delete_user(user_id: str, current_user = Depends(get_current_user)):
...

Comment Ajouter un Nouveau Endpoint Protégé

from fastapi import APIRouter, Depends
from app.utils.dependencies import get_current_student

router = APIRouter()

@router.get("/my-protected-endpoint")
async def my_endpoint(current_user = Depends(get_current_student)):
"""
Endpoint accessible uniquement aux étudiants.
current_user.user_type == UserType.STUDENT est garanti.
"""
student_id = current_user.id
...

Règles de Sécurité

Règle absolue

Les permissions ne doivent JAMAIS être gérées côté frontend. Le frontend peut adapter son UI (masquer/afficher des boutons), mais le backend doit toujours refuser les requêtes non autorisées — indépendamment de ce que le frontend affiche.

  1. Toujours utiliser une dépendance : Chaque endpoint protégé doit avoir Depends(...) avec le bon rôle.
  2. Isolation des données : Un UNIVERSITY_ADMIN ne peut accéder qu'aux données de son université (filtrer par university_id).
  3. Pas de confiance au JWT pour les données : Le JWT dit qui vous êtes, pas quelles données vous pouvez voir — vérifier sur chaque requête.

Fichiers de Référence

FichierContenu
app/core/config.pyDéfinition de UserType enum
app/utils/dependencies.pyDépendances FastAPI par rôle
app/utils/decorators.pyDécorateurs de sécurité
app/utils/auth.pyverify_token(), create_tokens()