Présentation
Projet académique du semestre 5 du BUT, réalisé en trinôme à l’IUT Montpellier-Sète. L’objectif : doter Push Start, une association qui soutient les créateurs de jeux vidéo et les acteurs de la culture numérique, d’une plateforme pour organiser ses événements thématiques — rencontres professionnelles, ateliers créatifs, conférences.
L’application repose sur une architecture découplée : une API REST développée avec Symfony et API Platform d’un côté, un client Vue.js autonome de l’autre, les deux communiquant uniquement par HTTP et authentifiés par jeton JWT.
- Trois rôles distincts : participant, organisateur et administrateur, avec des permissions différenciées
- Cycle complet de l’événement : création par un organisateur, inscription et désinscription des participants, consultation des inscrits
- Deux mois de développement répartis en deux temps : conception de l’API (octobre-novembre), puis intégration du front-end (décembre)
Mon rôle : conception de l’API
Modèle de domaine et règles métier
J’ai pris en charge la modélisation et l’implémentation du cœur métier, autour des entités Event, Subscription et User.
- Entité
Eventavec ses informations générales et ses attributs spécifiques au thème de l’événement - Validation systématique à la création : prix cohérent (strictement positif si l’événement est payant), nombre maximal de participants valide, refus de toute date déjà passée
- Attribution automatique de l’organisateur à partir de l’utilisateur connecté, la création étant réservée au rôle
ROLE_ORGANIZER - Entité
Subscriptionportant les règles d’inscription : vérification de l’existence de l’utilisateur et de l’événement, contrôle des places restantes, et impossibilité de s’inscrire à deux événements qui se chevauchent - Suppression en cascade : supprimer un utilisateur retire aussi les événements dont il est l’organisateur
Sécurité et gestion des rôles
- Authentification JWT via LexikJWTAuthenticationBundle, le jeton étant transporté par cookie plutôt que par en-tête, grâce à un listener sur le succès d’authentification
- Pare-feu
stateless: aucune session côté serveur, l’API reste entièrement sans état - Point d’entrée
json_loginsur/api/auth, authentifiant sur le champloginde l’entitéUser - Hiérarchie de rôles
ROLE_ORGANIZER → ROLE_USER, complétée parROLE_ADMIN - Règles d’accès fines : seul l’organisateur peut modifier son événement, l’organisateur ou un administrateur peuvent le supprimer, et chaque utilisateur ne gère que son propre profil
API Platform et principes SOLID
Plutôt que de concentrer la logique dans les entités, chaque comportement a été isolé dans une classe dédiée du cycle de vie API Platform — un découpage qui applique concrètement la responsabilité unique et l’inversion des dépendances.
- State Processors dédiés :
EventProcessorpour la création d’événements,SubscriptionEventProcessor,SubscriptionPutProcessoretSubscriptionDeleteProcessorpour les inscriptions,UserProcessorpour le hachage du mot de passe - State Provider
SubscriptionProviderpour exposer les collections croisées : les participants d’un événement, les événements d’un utilisateur - Normaliseur
EventAttributeNormalizerappliquant une sérialisation conditionnelle : l’organisateur décide si la liste des inscrits est publique ou non - Groupes de sérialisation pour contrôler précisément les champs exposés en lecture et acceptés en écriture
Outillage
- Commande console
create:userpermettant de provisionner des comptes avec leurs rôles depuis le terminal, indispensable pour peupler la base de test - Migrations Doctrine versionnées pour reconstruire le schéma à l’identique
Front-end Vue.js — travail d’équipe
La partie cliente a été développée collectivement en décembre, ma contribution portant sur l’intégration avec l’API et la cohérence du contrat d’échange.
- Vue 3 en TypeScript, construit avec Vite, qualité de code contrôlée par ESLint et
vue-tsc - Vue Router avec des routes protégées selon le rôle de l’utilisateur, réservant certaines vues aux organisateurs et aux administrateurs
- Composants réutilisables pour les formulaires (
FormulaireConnexion,FormulaireInscription,FormulaireEvent,FormulaireModification) et l’affichage des données (BoiteEvent,BoiteUtilisateur) - Appels API centralisés dans un module utilitaire
apiStore.ts, qui concentre la gestion du jeton JWT et le traitement des erreurs plutôt que de la disperser dans les vues
Infrastructure
- Docker Compose orchestrant deux services : un serveur Apache avec PHP 8.1 et une base MySQL persistée sur un volume
- HTTPS en local grâce à un certificat auto-signé et une configuration Apache dédiée
- Port du serveur de développement Vite exposé par le conteneur, pour travailler sur le front sans quitter l’environnement conteneurisé
- CORS géré par NelmioCorsBundle, nécessaire dès lors que le client et l’API sont servis sur des origines distinctes
- Installation reproductible en une commande, base de données et clés JWT générées via les commandes Symfony
Travail en équipe
- Trinôme avec une répartition explicite : entités et règles métier de mon côté, routes utilisateurs et tests d’API pour Victor, JWT et inscriptions pour Téo
- Versionnage sur le GitLab de l’IUT, travail sur une branche
developcommune, dépôt ensuite miroité sur GitHub - Synchronisations régulières et relectures croisées, notamment sur les questions de permissions où les décisions d’un membre affectent directement le travail des autres
- Documentation partagée dans le README : installation et configuration de mon côté, routes et peuplement de la base côté Victor
Technologies
- Back-end : Symfony 6.4, API Platform 4, PHP 8.1, Doctrine ORM 3, LexikJWTAuthenticationBundle 3.1, NelmioCorsBundle
- Front-end : Vue 3.5, TypeScript 5.6, Vite 6, Vue Router 4, ESLint 9
- Infrastructure : Docker Compose, Apache, MySQL
Ce que j’en retire
- Concevoir une API sans état change la façon de penser l’authentification : tout doit tenir dans le jeton, plus rien ne peut reposer sur une session
- Le découpage en processors d’API Platform rend les principes SOLID très concrets — chaque règle métier a son fichier, et les entités restent lisibles
- Une architecture découplée impose un contrat clair entre les deux moitiés de l’équipe : la moindre ambiguïté sur un format de réponse se paie immédiatement côté client


