# Analyse de l'API C# SkydiveLogs - Architecture et Fonctionnement ## Vue d'ensemble L'API **SkydiveLogs** est une application ASP.NET Core MVC développée avec une architecture modulaire propre, divisée en six projets distincts qui reposent sur une architecture en couches (Layered Architecture) : ### Structure du Projet ``` SkydiveLogs/Back/ ├── skydiveLogs-api/ # Projet principal (Web API + Point d'entrée) ├── skydiveLogs-api.Domain/ # Modèles de domaine (Entités) ├── skydiveLogs-api.DomainBusiness/ # Couche business logique (Services) ├── skydiveLogs-api.DomainService/ # Couche d'accès aux données (Repositories) ├── skydiveLogs-api.Infrastructure/ # Implémentations des repositories ├── skydiveLogs-api.Ioc/ # Service d'injection de dépendances └── skydiveLogs-api.sln # Fichier de solution ``` ## 1. Architecture des Couches ### 1.1 Architecture Clean/Modulaire L'API suit le **pattern Clean Architecture** avec une séparation claire des responsabilités : ``` ┌─────────────────────────────────────────────────────┐ │ skydiveLogs-api (Presentation Layer) │ │ - Controllers │ │ - Program.cs / Startup.cs │ └────────────────┬────────────────────────────────────┘ │ ┌────────────────▼────────────────────────────────────┐ │ skydiveLogs-api.Ioc (Dependency Injection) │ │ - Configuration IoC │ └────────────────┬────────────────────────────────────┘ │ ┌────────────────▼────────────────────────────────────┐ │ skydiveLogs-api.DomainBusiness (Business Layer) │ │ - Services (Interfaces + Implémentations) │ │ - Logique métier │ └────────────────┬────────────────────────────────────┘ │ ┌────────────────▼────────────────────────────────────┐ │ skydiveLogs-api.DomainService (Data Access Layer) │ │ - Repositories (Interfaces) │ └────────────────┬────────────────────────────────────┘ │ ┌────────────────▼────────────────────────────────────┐ │ skydiveLogs-api.Infrastructure (Implementation) │ │ - Repositories implémentés │ │ - LiteDbProvider │ └────────────────┬────────────────────────────────────┘ │ ┌────────────────▼────────────────────────────────────┐ │ skydiveLogs-api.Domain (Domain Layer) │ │ - Modèles de données (Entities) │ └─────────────────────────────────────────────────────┘ ``` ### 1.2 Injection de Dépendances (IocService) Le projet **skydiveLogs-api.Ioc** gère toute l'injection de dépendances via la classe `IocService` : #### Services Injectés - **Aircraft**, **Gear**, **DropZone**, **Jump**, **JumpType**, **Tunnel**, **User** et leurs services - **Stats** services (analytique) - **CacheService** (singleton pour le cache) - **IdentityService** (authentification) - **Repositories** pour chaque entité - **LiteDbProvider** (fournisseur de données LiteDB) ```csharp services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); // ... et ainsi de suite pour tous les services ``` ## 2. Configuration de l'Application (Startup.cs) ### 2.1 Configuration de l'Application Le fichier **Startup.cs** configure : 1. **Authentication JWT** - Validation du token JWT avec : - Vérification de l'émetteur (issuer) - Vérification de l'audience (audience) - Vérification de l'expiration (lifetime) - Validation de la clé de signature 2. **CORS** - Configuration pour autoriser la communication avec l'application front-end 3. **Initialisation de la Base de Données** - Vérification de l'existence du fichier LiteDB - Appel à `InitDbService.GenerateDb()` si le fichier n'existe pas - Appel à `InitDbService.Update()` si le fichier existe ### 2.2 Programme Principal (Program.cs) ```csharp public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args).UseStartup(); ``` ## 3. Architecture des Contrôleurs Tous les contrôleurs héritent de la classe de base `Base` : ### 3.1 Classe Base ```csharp [Route("api/[controller]")] [ApiController] [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] public class Base : ControllerBase { } ``` **Annotations importantes :** - `Route("api/[controller]")` : Préfixe "api/" pour toutes les routes - `ApiController` : Optimisations pour les API - `Authorize` : Requêtes authentifiées via JWT ### 3.2 Structure Type des Contrôleurs Chaque contrôleur suit le même pattern : ```csharp public class XxxController : Base { public XxxController(IxxxService xxxService, IMapper mapper) { _xxxService = xxxService; _mapper = mapper; } [HttpGet] public IEnumerable Get() { ... } [HttpGet("{id}")] public XxxResp Get(int id) { ... } [HttpPost] public void Post([FromBody] XxxReq value) { ... } [HttpPut("{id}")] public void Put(int id, [FromBody] XxxReq value) { ... } [HttpDelete("{id}")] public void Delete(int id) { ... } } ``` ## 4. Entités de Domaine (skydiveLogs-api.Domain) ### 4.1 Entités Principales #### **Jump** (Saut de parachutisme) ```csharp public class Jump { public Aircraft Aircraft { get; set; } public int DeployAltitude { get; set; } public DropZone DropZone { get; set; } public int ExitAltitude { get; set; } public Gear Gear { get; set; } public int Id { get; set; } public bool IsSpecial { get; set; } public DateTime JumpDate { get; set; } public JumpType JumpType { get; set; } public string Notes { get; set; } public User User { get; set; } public bool WithCutaway { get; set; } } ``` **Autres entités :** - **Aircraft** : Données des aéronefs - **User** : Utilisateurs (avec authentification) - **DropZone** : Zones de parachute (parachute drops) - **Gear** : Équipement - **JumpType** : Types de sauts - **Tunnel** : Données de tunnels - **TunnelFlight** : Vols de tunnel - **CacheType** : Types de cache #### **User** (avec authentification) ```csharp public class User { public string Email { get; set; } public string FirstName { get; set; } public int Id { get; set; } public bool IsAdmin { get; set; } public string Language { get; set; } public string LastName { get; set; } public string Login { get; set; } public string Password { get; set; } } ``` ### 4.2 Modèles de Statistiques Des entités dédiées pour les statistiques : - `Statistic` - Statistiques générales - `StatsByAircraft` - Statistiques par aéronef - `StatsByDz` - Statistiques par zone de parachute - `StatsByGear` - Statistiques par équipement - `StatsByJumpType` - Statistiques par type de saut - `StatsByYear` - Statistiques par année - `StatsByYearByJumpType` - Statistiques croisées année/type - `StatsForLastMonthByDz` - Statistiques du dernier mois - `StatsForLastYearByDz` - Statistiques de l'année dernière ## 5. Services de Business Logic (skydiveLogs-api.DomainBusiness) ### 5.1 Services Disponibles Chaque service implémente une interface dans `Interfaces` : #### Services CRUD - `AircraftService` - Gestion des aéronefs - `DropZoneService` - Gestion des zones de parachute - `GearService` - Gestion de l'équipement - `JumpService` - Gestion des sauts (principal) - `JumpTypeService` - Gestion des types de sauts - `TunnelService` - Gestion des tunnels - `TunnelFlightService` - Gestion des vols de tunnel - `UserImageService` - Gestion des images utilisateurs - `UserService` - Gestion des utilisateurs #### Services de Cache - `CacheService` - Gestion du cache - `IdentityService` - Gestion de l'identité/authentification #### Services d'Initialisation - `InitDbService` - Initialisation de la base de données #### Services Statistiques - `StatsService` - Statistiques générales - `StatsByAircraftService` - Par aéronef - `StatsByDzService` - Par zone de parachute - `StatsByGearService` - Par équipement - `StatsByJumpTypeService` - Par type de saut - `StatsByYearService` - Par année - `StatsByYearByJumpTypeService` - Croisé année/type - `StatsForLastMonthByDzService` - Dernier mois - `StatsForLastMonthByJumpTypeService` - Dernier mois - `StatsForLastYearByDzService` - Dernière année - `StatsForLastYearByJumpTypeService` - Dernière année ### 5.2 Implémentations de Services (ex: JumpService) Les services implémentent la logique métier et utilisent les repositories : ```csharp public class JumpService : IJumpService { private readonly IJumpRepository _jumpRepository; private readonly IMapper _mapper; public void AddNewJump(...) { ... } public void DeleteJumpById(int id) { ... } public IEnumerable GetAllJumps() { ... } public Jump GetJumpById(int id) { ... } public Jump GetJumpByUserAndDate(...) { ... } public int GetJumpCount() { ... } public IEnumerable GetJumpsByIndexes(...) { ... } public Jump UpdateJump(int id, Jump jump) { ... } } ``` ## 6. Répositories (skydiveLogs-api.DomainService et Infrastructure) ### 6.1 Couche DomainService Contient uniquement les interfaces `IxxxRepository` qui définissent le contrat d'accès aux données. ### 6.2 Couche Infrastructure Implémente concrètement les repositories avec **LiteDB** (base de données fichier NoSQL) : ```csharp public class JumpRepository : IJumpRepository { private readonly IDataProvider _dataProvider; private readonly IRepository _jumpCollection; // Implémentation concrète } ``` **LiteDbProvider** est utilisé comme fournisseur de données pour l'accès au fichier LiteDB. ## 7. Gestion des Données (Data) ### 7.1 Structure du Folder Data ``` skydiveLogs-api/Data/ ├── Aircraft/ ├── DropZone/ ├── FavoriteDropZone/ ├── Gear/ ├── Image/ ├── Jump/ ├── JumpType/ ├── StatsByAircraft/ ├── StatsByDz/ ├── StatsByGear/ ├── StatsByJumpType/ ├── StatsByYear/ ├── StatsByYearByJumpType/ ├── StatsForLastMonthByDz/ ├── StatsForLastMonthByJumpType/ ├── StatsForLastYearByDz/ ├── StatsForLastYearByJumpType/ ├── Tunnel/ ├── TunnelFlight/ └── User/ ``` Chaque dossier correspond à une collection LiteDB. ### 7.2 Contrats de Données (DataContract) Les fichiers `DataContract` contiennent les DTOs (Data Transfer Objects) : #### Requête (Req) - `AircraftReq`, `DropZoneReq`, `GearReq`, `JumpReq`, `JumpTypeReq` - `UserReq`, `TunnelFlightReq`, `ImageReq` #### Réponse (Resp) - `AircraftResp`, `AircraftSimpleResp`, `DropZoneResp`, `DropZoneSimpleResp` - `GearResp`, `JumpResp`, `JumpListResp`, `JumpTypeResp` - `UserResp`, `TunnelResp`, `TunnelFlightResp`, `ImageResp` - `StatisticResp`, `StatisticForChartResp` - `SimpleSummaryResp` #### Statistiques - `StatsForLastMonthByDzResp` - `StatsForLastYearByDzResp` ## 8. Mappage avec AutoMapper ### 8.1 Configuration AutoMapper Le fichier **Mapper** contient le profile d'AutoMapper pour mapper entre : - Domain entities (Aircraft, User, Jump, etc.) - DTOs (AircraftResp, UserResp, JumpResp, etc.) ```csharp public class ModelProfile : Profile { public ModelProfile() { // Configuration des mappages CreateMap(); CreateMap(); CreateMap(); // ... etc } } ``` ### 8.2 Utilisation dans les Contrôleurs ```csharp public JumpListResp Get() { var tmp = _jumpService.GetAllJumps(); var result = new JumpListResp { Rows = _mapper.Map>(tmp), Count = tmp.Count() }; return result; } ``` ## 9. Authentification JWT ### 9.1 Configuration JWT (Startup.cs) ```csharp var jwtSection = Configuration.GetSection("JWT"); services.Configure(jwtSection); services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.SaveToken = true; options.TokenValidationParameters = new TokenValidationParameters() { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = jwtSettings.Issuer, ValidAudience = jwtSettings.Issuer, IssuerSigningKey = new SymmetricSecurityKey( Encoding.UTF8.GetBytes(jwtSettings.Passphrase)) }; }); ``` ### 9.2 Token Generation (UserController) ```csharp private string CreateToken(UserResp foundUser) { var key = new SymmetricSecurityKey( Encoding.UTF8.GetBytes(_jwtConf.Passphrase)); var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: _jwtConf.Issuer, audience: _jwtConf.Issuer, expires: DateTime.Now.AddDays(1), signingCredentials: credentials, claims: new Claim[] { new Claim(ClaimTypes.Name, foundUser.Login), new Claim(ClaimTypes.UserData, foundUser.Id.ToString()), new Claim(ClaimTypes.Email, foundUser.Email), new Claim(ClaimTypes.Role, foundUser.Roles), new Claim("Language", foundUser.Language ?? "") }); return new JwtSecurityTokenHandler().WriteToken(token); } ``` ## 10. Endpoints API Disponibles ### 10.1 Routes par Contrôleur #### `/api/Jump` - `GET /api/Jump` - Liste tous les sauts - `GET /api/Jump/{id}` - Get par ID - `GET /api/Jump/{beginJumpIndex}/{endJumpIndex}` - Pagination - `POST /api/Jump` - Créer un saut - `PUT /api/Jump/{id}` - Mettre à jour - `DELETE /api/Jump/{id}` - Supprimer #### `/api/User` - `GET /api/User/AlwaysLogin` - Vérification connexion - `POST /api/User/Authenticate` - Authentification - `POST /api/User` - Créer un utilisateur #### `/api/Aircraft` - `GET /api/Aircraft` - Liste - `GET /api/Aircraft/{id}` - Get - `GET /api/Aircraft/GetSimple` - Liste simplifiée - `POST /api/Aircraft` - Créer - `PUT /api/Aircraft/{id}` - Mettre à jour - `DELETE /api/Aircraft/{id}` - Supprimer #### `/api/DropZone` - `GET /api/DropZone` - Liste - `GET /api/DropZone/{id}` - Get - `GET /api/DropZone/GetSimple` - Liste simplifiée - `POST /api/DropZone` - Créer - `PUT /api/DropZone/{id}` - Mettre à jour - `DELETE /api/DropZone/{id}` - Supprimer - `PUT /api/DropZone/AddToFavorite/{id}` - Ajouter aux favoris - `PUT /api/DropZone/RemoveToFavorite/{id}` - Retirer des favoris #### `/api/Gear` - `GET /api/Gear` - Liste - `GET /api/Gear/{id}` - Get - `POST /api/Gear` - Créer - `PUT /api/Gear/{id}` - Mettre à jour - `DELETE /api/Gear/{id}` - Supprimer #### `/api/JumpType` - `GET /api/JumpType` - Liste - `GET /api/JumpType/tunnel` - Types pour tunnel - `GET /api/JumpType/{id}` - Get - `POST /api/JumpType` - Créer - `PUT /api/JumpType/{id}` - Mettre à jour - `DELETE /api/JumpType/{id}` - Supprimer #### `/api/Tunnel` - `GET /api/Tunnel` - Liste - `GET /api/Tunnel/{id}` - Get #### `/api/TunnelFlight` - Routes pour gestion des vols tunnel #### `/api/Image` - `GET /api/Image` - Liste - `GET /api/Image/{id}` - Get - `POST /api/Image` - Créer - `PUT /api/Image/{id}` - Mettre à jour - `DELETE /api/Image/{id}` - Supprimer #### `/api/Stats` - `GET /api/Stats/ByAircraft` - Stats par aéronef - `GET /api/Stats/ByDz` - Stats par zone - `GET /api/Stats/ByGear` - Stats par équipement - `GET /api/Stats/ByJumpType` - Stats par type - `GET /api/Stats/ByYear` - Stats par année - `GET /api/Stats/ByYearByJumpType` - Stats croisées - `GET /api/Stats/ForLastMonth` - Stats du mois dernier - `GET /api/Stats/ForLastYear` - Stats de l'année dernière - `GET /api/Stats/Simple` - Résumé simple - `GET /api/Stats/Reset` - Réinitialiser les stats ## 11. Gestion de Configuration ### 11.1 Fichiers appsettings Les configurations sont stockées dans : - `appsettings.json` - Configuration par défaut - `appsettings.Development.json` - Configuration de développement - `appsettings.Release.json` - Configuration de production ### 11.2 Sections de Configuration - **JWT** - Configuration JWT (issuer, passphrase) - **Cors** - Configuration CORS (frontUrl) - **ConnectionStrings** - Connexion LiteDB (Filename) ## 12. Initialisation de la Base de Données Le fichier `CheckAndInitDb` dans `Startup.cs` s'assure que : 1. Le fichier LiteDB existe 2. Si non, `InitDbService.GenerateDb()` crée la structure 3. Si oui, `InitDbService.Update()` met à jour la structure ## 13. Bonnes Pratiques Observées ### 13.1 Séparation des Responsabilités - Les contrôleurs ne font que manipuler les requêtes/réponses - La logique métier est dans les services - L'accès aux données est dans les repositories ### 13.2 Sécurité - Authentification JWT - Autorisation par rôle (admin flag) - Validation des tokens - HSTS en production ### 13.3 Gestion des Erreurs - Développement avec `UseDeveloperExceptionPage()` - Production avec HSTS - Gestion des erreurs via services ### 13.4 Performance - Pagination des listes (par index) - Cache avec `CacheService` - AutoMapper pour éviter le code répétitif ## 14. Conclusion L'API **SkydiveLogs** est une application C# robuste et bien structurée, utilisant : - **ASP.NET Core MVC** avec API - **LiteDB** comme base de données fichier - **JWT** pour l'authentification - **AutoMapper** pour le mappage - **Injection de dépendances** via `IocService` L'architecture en couches assure une maintenabilité et une extensibilité optimales pour une application de journalisation de parachutisme.