Little test with AI + Add the equipment #8
+571
@@ -0,0 +1,571 @@
|
||||
# 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<IAircraftService, AircraftService>();
|
||||
services.AddScoped<IGearService, GearService>();
|
||||
services.AddScoped<IDropZoneService, DropZoneService>();
|
||||
services.AddScoped<IJumpService, JumpService>();
|
||||
// ... 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<Startup>();
|
||||
```
|
||||
|
||||
## 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<XxxResp> 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<Jump> GetAllJumps() { ... }
|
||||
public Jump GetJumpById(int id) { ... }
|
||||
public Jump GetJumpByUserAndDate(...) { ... }
|
||||
public int GetJumpCount() { ... }
|
||||
public IEnumerable<Jump> 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<Jump> _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<User, UserResp>();
|
||||
CreateMap<Aircraft, AircraftResp>();
|
||||
CreateMap<Jump, JumpResp>();
|
||||
// ... etc
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8.2 Utilisation dans les Contrôleurs
|
||||
|
||||
```csharp
|
||||
public JumpListResp Get()
|
||||
{
|
||||
var tmp = _jumpService.GetAllJumps();
|
||||
var result = new JumpListResp
|
||||
{
|
||||
Rows = _mapper.Map<IEnumerable<JumpResp>>(tmp),
|
||||
Count = tmp.Count()
|
||||
};
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
## 9. Authentification JWT
|
||||
|
||||
### 9.1 Configuration JWT (Startup.cs)
|
||||
|
||||
```csharp
|
||||
var jwtSection = Configuration.GetSection("JWT");
|
||||
services.Configure<JwtSettings>(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.
|
||||
@@ -1,10 +1,10 @@
|
||||
using AutoMapper;
|
||||
using System.Collections.Generic;
|
||||
using AutoMapper;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using skydiveLogs_api.DataContract;
|
||||
using skydiveLogs_api.Domain;
|
||||
using skydiveLogs_api.DomainBusiness.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace skydiveLogs_api.Controllers
|
||||
{
|
||||
@@ -23,7 +23,10 @@ namespace skydiveLogs_api.Controllers
|
||||
|
||||
#region Public Methods
|
||||
|
||||
// DELETE: api/ApiWithActions/5
|
||||
/// <summary>
|
||||
/// Deletes an aircraft by its ID.
|
||||
/// </summary>
|
||||
/// <param name="id">The aircraft ID to delete.</param>
|
||||
[HttpDelete("{id}")]
|
||||
[EnableCors]
|
||||
public void Delete(int id)
|
||||
@@ -31,7 +34,10 @@ namespace skydiveLogs_api.Controllers
|
||||
_aircraftService.DeleteAircraftById(id);
|
||||
}
|
||||
|
||||
// GET: api/Aircraft
|
||||
/// <summary>
|
||||
/// Retrieves a list of all aircraft.
|
||||
/// </summary>
|
||||
/// <returns>A collection of AircraftResp objects containing all aircraft data.</returns>
|
||||
[HttpGet]
|
||||
[EnableCors]
|
||||
public IEnumerable<AircraftResp> Get()
|
||||
@@ -40,7 +46,11 @@ namespace skydiveLogs_api.Controllers
|
||||
return _mapper.Map<IEnumerable<AircraftResp>>(result);
|
||||
}
|
||||
|
||||
// GET: api/Aircraft/5
|
||||
/// <summary>
|
||||
/// Retrieves an aircraft by its ID.
|
||||
/// </summary>
|
||||
/// <param name="id">The aircraft ID to retrieve.</param>
|
||||
/// <returns>An AircraftResp object containing the aircraft details.</returns>
|
||||
[HttpGet("{id}")]
|
||||
[EnableCors]
|
||||
public AircraftResp Get(int id)
|
||||
@@ -49,6 +59,10 @@ namespace skydiveLogs_api.Controllers
|
||||
return _mapper.Map<AircraftResp>(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a simplified list of all aircraft.
|
||||
/// </summary>
|
||||
/// <returns>A collection of AircraftSimpleResp objects containing simplified aircraft data.</returns>
|
||||
[HttpGet("GetSimple")]
|
||||
[EnableCors]
|
||||
public IEnumerable<AircraftSimpleResp> GetSimple()
|
||||
@@ -57,7 +71,10 @@ namespace skydiveLogs_api.Controllers
|
||||
return _mapper.Map<IEnumerable<AircraftSimpleResp>>(result);
|
||||
}
|
||||
|
||||
// POST: api/Aircraft
|
||||
/// <summary>
|
||||
/// Adds a new aircraft to the system.
|
||||
/// </summary>
|
||||
/// <param name="value">AircraftReq object containing the new aircraft data.</param>
|
||||
[HttpPost]
|
||||
[EnableCors]
|
||||
public void Post([FromBody] AircraftReq value)
|
||||
@@ -65,7 +82,11 @@ namespace skydiveLogs_api.Controllers
|
||||
_aircraftService.AddNewAircraft(_mapper.Map<Aircraft>(value));
|
||||
}
|
||||
|
||||
// PUT: api/Aircraft/5
|
||||
/// <summary>
|
||||
/// Updates an existing aircraft.
|
||||
/// </summary>
|
||||
/// <param name="id">The aircraft ID to update.</param>
|
||||
/// <param name="value">AircraftReq object containing the updated aircraft data.</param>
|
||||
[HttpPut("{id}")]
|
||||
[EnableCors]
|
||||
public void Put(int id, [FromBody] AircraftReq value)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using AutoMapper;
|
||||
using System.Collections.Generic;
|
||||
using AutoMapper;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using skydiveLogs_api.DataContract;
|
||||
using skydiveLogs_api.Domain;
|
||||
using skydiveLogs_api.DomainBusiness.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace skydiveLogs_api.Controllers
|
||||
{
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using AutoMapper;
|
||||
using System.Collections.Generic;
|
||||
using AutoMapper;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using skydiveLogs_api.DataContract;
|
||||
using skydiveLogs_api.Domain;
|
||||
using skydiveLogs_api.DomainBusiness.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace skydiveLogs_api.Controllers
|
||||
{
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using AutoMapper;
|
||||
using System.Collections.Generic;
|
||||
using AutoMapper;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using skydiveLogs_api.DataContract;
|
||||
using skydiveLogs_api.Domain;
|
||||
using skydiveLogs_api.DomainBusiness.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace skydiveLogs_api.Controllers
|
||||
{
|
||||
|
||||
@@ -24,7 +24,10 @@ namespace skydiveLogs_api.Controllers
|
||||
|
||||
#region Public Methods
|
||||
|
||||
// DELETE: api/Jump/5
|
||||
/// <summary>
|
||||
/// Deletes a jump by its ID.
|
||||
/// </summary>
|
||||
/// <param name="id">The jump ID to delete.</param>
|
||||
[HttpDelete("{id}")]
|
||||
[EnableCors]
|
||||
public void Delete(int id)
|
||||
@@ -32,7 +35,10 @@ namespace skydiveLogs_api.Controllers
|
||||
_jumpService.DeleteJumpById(id);
|
||||
}
|
||||
|
||||
// GET: api/Jump
|
||||
/// <summary>
|
||||
/// Retrieves a list of all jumps.
|
||||
/// </summary>
|
||||
/// <returns>A JumpListResp containing all jumps and their count.</returns>
|
||||
[HttpGet]
|
||||
[EnableCors]
|
||||
public JumpListResp Get()
|
||||
@@ -47,7 +53,12 @@ namespace skydiveLogs_api.Controllers
|
||||
return result;
|
||||
}
|
||||
|
||||
// GET: api/Jump/5/10
|
||||
/// <summary>
|
||||
/// Retrieves a page of jumps with pagination.
|
||||
/// </summary>
|
||||
/// <param name="beginJumpIndex">The starting index for pagination.</param>
|
||||
/// <param name="endJumpIndex">The ending index for pagination.</param>
|
||||
/// <returns>A JumpListResp containing the requested page and total count.</returns>
|
||||
[HttpGet("{beginJumpIndex}/{endJumpIndex}")]
|
||||
[EnableCors]
|
||||
public JumpListResp Get(int beginJumpIndex, int endJumpIndex)
|
||||
@@ -63,7 +74,11 @@ namespace skydiveLogs_api.Controllers
|
||||
return result;
|
||||
}
|
||||
|
||||
// GET: api/Jump/5
|
||||
/// <summary>
|
||||
/// Retrieves a jump by its ID.
|
||||
/// </summary>
|
||||
/// <param name="id">The jump ID to retrieve.</param>
|
||||
/// <returns>A JumpResp containing the jump details.</returns>
|
||||
[HttpGet("{id}")]
|
||||
[EnableCors]
|
||||
public JumpResp Get(int id)
|
||||
@@ -72,7 +87,10 @@ namespace skydiveLogs_api.Controllers
|
||||
return _mapper.Map<JumpResp>(result);
|
||||
}
|
||||
|
||||
// POST: api/Jump
|
||||
/// <summary>
|
||||
/// Adds a new jump to the system.
|
||||
/// </summary>
|
||||
/// <param name="value">JumpReq object containing the new jump data.</param>
|
||||
[HttpPost]
|
||||
[EnableCors]
|
||||
public void Post([FromBody] JumpReq value)
|
||||
@@ -84,7 +102,11 @@ namespace skydiveLogs_api.Controllers
|
||||
_mapper.Map<Jump>(value));
|
||||
}
|
||||
|
||||
// PUT: api/Jump/5
|
||||
/// <summary>
|
||||
/// Updates an existing jump.
|
||||
/// </summary>
|
||||
/// <param name="id">The jump ID to update.</param>
|
||||
/// <param name="value">JumpReq object containing the new jump data.</param>
|
||||
[HttpPut("{id}")]
|
||||
[EnableCors]
|
||||
public void Put(int id, [FromBody] JumpReq value)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using AutoMapper;
|
||||
using System.Collections.Generic;
|
||||
using AutoMapper;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using skydiveLogs_api.DataContract;
|
||||
using skydiveLogs_api.Domain;
|
||||
using skydiveLogs_api.DomainBusiness.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace skydiveLogs_api.Controllers
|
||||
{
|
||||
|
||||
@@ -22,6 +22,10 @@ namespace skydiveLogs_api.Controllers
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves statistics grouped by aircraft.
|
||||
/// </summary>
|
||||
/// <returns>A collection of StatisticResp objects containing aircraft statistics.</returns>
|
||||
[HttpGet("ByAircraft")]
|
||||
[EnableCors]
|
||||
public IEnumerable<StatisticResp> ByAircraft()
|
||||
@@ -31,6 +35,10 @@ namespace skydiveLogs_api.Controllers
|
||||
return _mapper.Map<IEnumerable<StatisticResp>>(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves statistics grouped by drop zone.
|
||||
/// </summary>
|
||||
/// <returns>A collection of StatisticResp objects containing drop zone statistics.</returns>
|
||||
[HttpGet("ByDz")]
|
||||
[EnableCors]
|
||||
public IEnumerable<StatisticResp> ByDz()
|
||||
@@ -40,6 +48,10 @@ namespace skydiveLogs_api.Controllers
|
||||
return _mapper.Map<IEnumerable<StatisticResp>>(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves statistics grouped by gear.
|
||||
/// </summary>
|
||||
/// <returns>A collection of StatisticResp objects containing gear statistics.</returns>
|
||||
[HttpGet("ByGear")]
|
||||
[EnableCors]
|
||||
public IEnumerable<StatisticResp> ByGear()
|
||||
@@ -49,6 +61,10 @@ namespace skydiveLogs_api.Controllers
|
||||
return _mapper.Map<IEnumerable<StatisticResp>>(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves statistics grouped by jump type.
|
||||
/// </summary>
|
||||
/// <returns>A collection of StatisticResp objects containing jump type statistics.</returns>
|
||||
[HttpGet("ByJumpType")]
|
||||
[EnableCors]
|
||||
public IEnumerable<StatisticResp> ByJumpType()
|
||||
@@ -58,6 +74,10 @@ namespace skydiveLogs_api.Controllers
|
||||
return _mapper.Map<IEnumerable<StatisticResp>>(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves statistics grouped by year.
|
||||
/// </summary>
|
||||
/// <returns>A collection of StatisticResp objects containing year statistics.</returns>
|
||||
[HttpGet("ByYear")]
|
||||
[EnableCors]
|
||||
public IEnumerable<StatisticResp> ByYear()
|
||||
@@ -67,6 +87,10 @@ namespace skydiveLogs_api.Controllers
|
||||
return _mapper.Map<IEnumerable<StatisticResp>>(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves statistics for the last month grouped by drop zone and jump type.
|
||||
/// </summary>
|
||||
/// <returns>A StatisticForLastMonthResp object containing last month statistics.</returns>
|
||||
[HttpGet("ForLastMonth")]
|
||||
[EnableCors]
|
||||
public StatisticForLastMonthResp ForLastMonth()
|
||||
@@ -81,6 +105,10 @@ namespace skydiveLogs_api.Controllers
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves statistics for the last year grouped by drop zone and jump type.
|
||||
/// </summary>
|
||||
/// <returns>A StatisticForLastYearResp object containing last year statistics.</returns>
|
||||
[HttpGet("ForLastYear")]
|
||||
[EnableCors]
|
||||
public StatisticForLastYearResp ForLastYear()
|
||||
@@ -95,6 +123,10 @@ namespace skydiveLogs_api.Controllers
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves statistics by year grouped with jump type for chart visualization.
|
||||
/// </summary>
|
||||
/// <returns>A collection of StatisticForChartResp objects containing yearly jump type statistics.</returns>
|
||||
[HttpGet("ByYearByJumpType")]
|
||||
[EnableCors]
|
||||
public IEnumerable<StatisticForChartResp> ByYearByJumpType()
|
||||
@@ -104,6 +136,9 @@ namespace skydiveLogs_api.Controllers
|
||||
return _mapper.Map<IEnumerable<StatisticForChartResp>>(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets all statistics to their initial state.
|
||||
/// </summary>
|
||||
[HttpGet("Reset")]
|
||||
[EnableCors]
|
||||
public void Reset()
|
||||
@@ -111,6 +146,10 @@ namespace skydiveLogs_api.Controllers
|
||||
_statsService.Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a simple summary of all statistics.
|
||||
/// </summary>
|
||||
/// <returns>A SimpleSummaryResp object containing the simple summary statistics.</returns>
|
||||
[HttpGet("Simple")]
|
||||
[EnableCors]
|
||||
public SimpleSummaryResp Simple()
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using AutoMapper;
|
||||
using System.Collections.Generic;
|
||||
using AutoMapper;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using skydiveLogs_api.DataContract;
|
||||
using skydiveLogs_api.DomainBusiness.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace skydiveLogs_api.Controllers
|
||||
{
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using AutoMapper;
|
||||
using System.Collections.Generic;
|
||||
using AutoMapper;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using skydiveLogs_api.DataContract;
|
||||
using skydiveLogs_api.Domain;
|
||||
using skydiveLogs_api.DomainBusiness.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace skydiveLogs_api.Controllers
|
||||
{
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
using AutoMapper;
|
||||
using System;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using AutoMapper;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@@ -8,10 +12,6 @@ using skydiveLogs_api.DataContract;
|
||||
using skydiveLogs_api.Domain;
|
||||
using skydiveLogs_api.DomainBusiness.Interfaces;
|
||||
using skydiveLogs_api.Settings;
|
||||
using System;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
|
||||
namespace skydiveLogs_api.Controllers
|
||||
{
|
||||
@@ -34,7 +34,10 @@ namespace skydiveLogs_api.Controllers
|
||||
|
||||
#region Public Methods
|
||||
|
||||
// GET: api/User/AlwayLogin
|
||||
/// <summary>
|
||||
/// Always login endpoint for testing authentication status.
|
||||
/// </summary>
|
||||
/// <returns>An Ok result indicating successful authentication.</returns>
|
||||
[HttpGet("AlwaysLogin")]
|
||||
[EnableCors]
|
||||
public IActionResult AlwaysLogin()
|
||||
@@ -42,7 +45,11 @@ namespace skydiveLogs_api.Controllers
|
||||
return Ok();
|
||||
}
|
||||
|
||||
// POST: api/User/Authenticate
|
||||
/// <summary>
|
||||
/// Authenticates a user with login and password.
|
||||
/// </summary>
|
||||
/// <param name="value">UserReq containing login and password.</param>
|
||||
/// <returns>UserResp with token if successful, BadRequest if failed.</returns>
|
||||
[AllowAnonymous]
|
||||
[HttpPost("Authenticate")]
|
||||
[EnableCors]
|
||||
@@ -67,7 +74,11 @@ namespace skydiveLogs_api.Controllers
|
||||
return result;
|
||||
}
|
||||
|
||||
// POST: api/User
|
||||
/// <summary>
|
||||
/// Creates a new user and returns JWT token.
|
||||
/// </summary>
|
||||
/// <param name="userToAdd">UserReq object containing new user data.</param>
|
||||
/// <returns>UserResp with token if successful, BadRequest on error.</returns>
|
||||
[AllowAnonymous]
|
||||
[HttpPost]
|
||||
[EnableCors]
|
||||
|
||||
Reference in New Issue
Block a user