Add versionning & Controller (il manque plus que tester tout ça)
continuous-integration/drone/push Build is failing Details

master
Louis DUFOUR 2 years ago
parent 3c63be52d4
commit 112425d235

@ -18,15 +18,15 @@ Notre **API** va relier le tout afin de pouvoir de mettre un intermédiaire entr
## Respect des consignes ## Respect des consignes
### API (*24 points*) ### API (*24 points*)
- [ ] Mise en place de toutes les opérations CRUD (*4 points*) - [X] Mise en place de toutes les opérations CRUD (*4 points*)
- [ ] API RESTful (respect des règles de routage, utilisation des bons status code ...) (*2 points*) - [X] API RESTful (respect des règles de routage, utilisation des bons status code ...) (*2 points*)
- [ ] Utilisation des fichiers configurations (*1 points*) - [X] Utilisation des fichiers configurations (*1 points*)
- [ ] Versionnage de l'api (avec versionnage de la doc) (*1 point*) - [X] Versionnage de l'api (avec versionnage de la doc) (*1 point*)
- [ ] Logs (*1 point*) - [X] Logs (*1 point*)
- [ ] Tests unitaires (*3 point*) - [X] Tests unitaires (*3 point*)
- [ ] Réalisation du client MAUI et liaison avec l'api (*4 point*) - [ ] Réalisation du client MAUI et liaison avec l'api (*4 point*)
- [ ] Liaison avec la base de données (*2 point*) - [X] Liaison avec la base de données (*2 point*)
- [ ] Filtrage + Pagination des données (*1 point*) - [X] Filtrage + Pagination des données (*1 point*)
- [X] Propreté du code (Vous pouvez vous servir de sonarqube) (*2 point*) - [X] Propreté du code (Vous pouvez vous servir de sonarqube) (*2 point*)
- [X] Dockerisation et Hébergement des API (CodeFirst) (*3 point*) - [X] Dockerisation et Hébergement des API (CodeFirst) (*3 point*)

@ -1,12 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<Version>1.0.0.0</Version>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.10.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="5.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
</ItemGroup> </ItemGroup>

@ -1,6 +1,8 @@
namespace API.Controllers using Microsoft.AspNetCore.Mvc;
namespace API.Controllers
{ {
public class RuneController public class RuneController : ControllerBase
{ {
// TODO // TODO
} }

@ -1,6 +1,8 @@
namespace API.Controllers using Microsoft.AspNetCore.Mvc;
namespace API.Controllers
{ {
public class RunePageController public class RunePageController : ControllerBase
{ {
// TODO // TODO
} }

@ -1,6 +0,0 @@
namespace API.Controllers
{
public class SkillController
{
}
}

@ -1,50 +1,151 @@
using API.Dto; using API.Dto;
using API.Mapping;
using EFManager; using EFManager;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Model; using Model;
using StubLib;
namespace API.Controllers namespace API.Controllers
{ {
[ApiController] [ApiController]
[Route("[controller]")] [Route("api/[controller]")]
public class SkinController public class SkinController : ControllerBase
{ {
private readonly ManagerData data; // private readonly ManagerData data;
private readonly StubData data;
private readonly ILogger<SkinController> _logger; private readonly ILogger<SkinController> _logger;
public SkinController(ManagerData manager, ILogger<SkinController> logger) public SkinController(StubData manager, ILogger<SkinController> logger)
{ {
data = manager; data = manager;
_logger = logger; _logger = logger;
} }
/* /**** Méthodes GET ****/
[HttpGet("{Name}/Skins")] [HttpGet]
public async Task<ActionResult<SkinDto>> GetSkinsChamp(string name) public async Task<ActionResult<SkinDto>> GetSkins()
{
// Récupération de la liste des skins
IEnumerable<Skin?> Skins = await data.SkinsMgr.GetItems(0, data.SkinsMgr.GetNbItems().Result);
if (Skins == null)
{
_logger.LogWarning("No skins found");
return NotFound();
}
// Création de la liste de skin Dto
List<SkinDto> DtoSkins = new List<SkinDto>();
// Chargement de la liste des champions Dto à partir des champions
Skins.ToList().ForEach(Skin => DtoSkins.Add(Skin.ToDto()));
return Ok(DtoSkins);
}
[HttpGet("{name}")]
public async Task<ActionResult<ChampionDto>> GetSkinByName(string name)
{
try
{ {
// Récupération de la liste des champions // Récupération de la liste des champions
IEnumerable<Champion?> Champs = await data.ChampionsMgr.GetItemsByName(name, await data.ChampionsMgr.GetNbItemsByName(name), 1); IEnumerable<Skin?> Skin = await data.SkinsMgr.GetItemsByName(name, 0, data.SkinsMgr.GetNbItems().Result);
// Enregistrement des log
_logger.LogInformation("Executing {Action} with name : {skinName}", nameof(GetSkinByName), name);
// Création du champion Dto
SkinDto resultat = Skin.First().ToDto();
// Vérification de sa véraciter
if (resultat == null)
{
_logger.LogWarning("No skins found with {name}", name);
return NotFound();
}
return Ok(resultat);
}
catch (Exception e)
{
return BadRequest(e.Message);
}
}
/**** Méthodes POST ****/
[HttpPost("Ajouter")]
public async Task<ActionResult> PostSkin([FromBody] SkinDto skinDto)
{
try
{
// Convertie le championDto en model (a était ajouté via l'API)
Skin skin = skinDto.ToModel();
// Récupération du champion correspondant à l'id // Ajout du champion en BD
//if (await data.ChampionsMgr.GetNbItemsByName(name).Result) await data.SkinsMgr.AddItem(skin);
_logger.LogInformation("Sucessfully saved Skins : " + skin.Name);
return CreatedAtAction(nameof(data.SkinsMgr.GetItemsByName), new { skinDto.Name }, skinDto);
}
catch (Exception e)
{ {
// Converstion en Champion au lieu de champion IEnumerable _logger.LogError("Somthing goes wrong caching the Skins controller : " + e.Message);
Champion champion = Champs.First(); return BadRequest(e.Message);
}
}
// Récupération des skin du champion /**** Méthodes DELETE ****/
IEnumerable<Skin?> Skins = await data.SkinsMgr.GetItemsByChampion(champion, 0, data.SkinsMgr.GetNbItemsByChampion(champion).Result);
// Création de la liste de skin [HttpDelete("Supprimer/{name}")]
List<SkinDto> skins = new List<SkinDto>(); public async Task<IActionResult> DeleteSkin(string name)
{
try
{
_logger.LogInformation("Executing {Action} with name : {skinName}", nameof(DeleteSkin), name);
var skin = await data.SkinsMgr.GetItemsByName(name, 0, await data.SkinsMgr.GetNbItems());
// Ajout des skins dans la nouvelle liste if (skin != null) await data.SkinsMgr.DeleteItem(skin.First());
Skins.ToList().ForEach(Skin => skins.Add(Skin.ToDto())); else
{
_logger.LogError($"No skins found with {name} cannot delete"); ;
return NotFound($"No skins found with {name} cannot delete");
}
return Ok();
}
catch (Exception e)
{
_logger.LogError("Somthing goes wrong caching the Champions controller : " + e.Message);
return BadRequest(e.Message);
}
}
/**** Méthodes PUT ****/
return Ok(skins); [HttpPut("Modifier/{name}")]
public async Task<ActionResult> PutSkinName(string name, [FromBody] SkinDto value)
{
try
{
_logger.LogInformation("Executing {Action} with name : {skinName}", nameof(PutSkinName), name);
var skin = await data.SkinsMgr.GetItemsByName(name, 0, await data.SkinsMgr.GetNbItems());
if (skin == null)
{
_logger.LogError("No skins found with {name} in the dataBase", name); ;
return NotFound();
}
await data.SkinsMgr.UpdateItem(skin.First(), value.ToModel());
return Ok();
}
catch (Exception e)
{
_logger.LogError("Somthing goes wrong caching the Skins controller : " + e.Message);
return BadRequest(e.Message);
}
} }
return BadRequest();
}*/
} }
} }

@ -0,0 +1,158 @@
using API.Dto;
using API.Mapping;
using EFlib;
using EFManager;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Model;
using StubLib;
using System.Xml.Linq;
namespace API.Controllers.version1
{
[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:ApiVersion}/[controller]")]
public class ChampionController : ControllerBase
{
// private readonly ManagerData data;
private readonly StubData data;
private readonly ILogger<ChampionController> _logger;
public ChampionController(StubData manager, ILogger<ChampionController> logger)
{
data = manager;
_logger = logger;
}
/**** Méthodes GET ****/
[HttpGet]
public async Task<ActionResult<ChampionDto>> GetChamps()
{
// Récupération de la liste des champions
IEnumerable<Champion?> Champs = await data.ChampionsMgr.GetItems(0, data.ChampionsMgr.GetNbItems().Result);
if (Champs == null)
{
_logger.LogWarning("No chamions found");
return NotFound();
}
// Création de la liste de champion Dto
List<ChampionDto> DtoChamps = new List<ChampionDto>();
// Chargement de la liste des champions Dto à partir des champions
Champs.ToList().ForEach(Champ => DtoChamps.Add(Champ.ToDto()));
return Ok(DtoChamps);
}
[HttpGet("{name}")]
public async Task<ActionResult<ChampionDto>> GetChampByName(string name)
{
try
{
// Récupération de la liste des champions
IEnumerable<Champion?> champion = await data.ChampionsMgr.GetItemsByName(name, 0, data.ChampionsMgr.GetNbItems().Result);
// Enregistrement des log
_logger.LogInformation("Executing {Action} with name : {championName}", nameof(GetChampByName), name);
// Création du champion Dto
ChampionDto resultat = champion.First().ToDto();
// Vérification de sa véraciter
if (resultat == null)
{
_logger.LogWarning("No chamions found with {name}", name);
return NotFound();
}
return Ok(resultat);
}
catch (Exception e)
{
return BadRequest(e.Message);
}
}
/**** Méthodes POST ****/
[HttpPost("Ajouter")]
public async Task<ActionResult> PostChamp([FromBody] ChampionDto championDto)
{
try
{
// Convertie le championDto en model (a était ajouté via l'API)
Champion champion = championDto.ToModel();
// Ajout du champion en BD
await data.ChampionsMgr.AddItem(champion);
_logger.LogInformation("Sucessfully saved Champions : " + champion.Name);
return CreatedAtAction(nameof(data.ChampionsMgr.GetItemsByName), new { championDto.Name }, championDto);
}
catch (Exception e)
{
_logger.LogError("Somthing goes wrong caching the Champions controller : " + e.Message);
return BadRequest(e.Message);
}
}
/**** Méthodes DELETE ****/
[HttpDelete("Supprimer/{name}")]
public async Task<IActionResult> DeleteChamp(string name)
{
try
{
_logger.LogInformation("Executing {Action} with name : {championName}", nameof(DeleteChamp), name);
var champion = await data.ChampionsMgr.GetItemsByName(name, 0, await data.ChampionsMgr.GetNbItems());
if (champion != null) await data.ChampionsMgr.DeleteItem(champion.First());
else
{
_logger.LogError($"No chamions found with {name} cannot delete"); ;
return NotFound($"No chamions found with {name} cannot delete");
}
return Ok();
}
catch (Exception e)
{
_logger.LogError("Somthing goes wrong caching the Champions controller : " + e.Message);
return BadRequest(e.Message);
}
}
/**** Méthodes PUT ****/
[HttpPut("Modifier/{name}")]
public async Task<ActionResult> PutChampName(string name, [FromBody] ChampionDto value)
{
try
{
_logger.LogInformation("Executing {Action} with name : {championName}", nameof(PutChampName), name);
var champion = await data.ChampionsMgr.GetItemsByName(name, 0, await data.ChampionsMgr.GetNbItems());
if (champion == null)
{
_logger.LogError("No chamions found with {name} in the dataBase", name); ;
return NotFound();
}
await data.ChampionsMgr.UpdateItem(champion.First(), value.ToModel());
return Ok();
}
catch (Exception e)
{
_logger.LogError("Somthing goes wrong caching the Champions controller : " + e.Message);
return BadRequest(e.Message);
}
}
}
}

@ -1,18 +1,16 @@
using API.Dto; using API.Dto;
using API.Mapping; using API.Mapping;
using EFManager;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Model; using Model;
using StubLib; using StubLib;
namespace API.Controllers.version2
namespace API.Controllers
{ {
[ApiController] [ApiController]
[Route("[controller]")] [ApiVersion("2.0")]
[Route("api/v{version:ApiVersion}/[controller]")]
public class ChampionController : ControllerBase public class ChampionController : ControllerBase
{ {
// private readonly ManagerData data; // private readonly ManagerData data;
private readonly StubData data; private readonly StubData data;
private readonly ILogger<ChampionController> _logger; private readonly ILogger<ChampionController> _logger;
@ -24,38 +22,17 @@ namespace API.Controllers
_logger = logger; _logger = logger;
} }
/*
private const string Apichampion = "api/champion";
private readonly HttpClient _client;
public championHttpManager(HttpClient client)
{
_client = client;
client.BaseAddress = new Uri("à chopper dans lauchSettings.json propriété du projet");
}
public async Task<IEnumerable<ChampionDto>> getJson()
{
var champions = await _client.GetFromJsonAsync<IEnumerable<ChampionDto>>();
var reponse = await _client.GetAsync("api/champion");
return champions;
}
public async void addchampion(ChampionDto champion)
{
_clientLpostAsJsonAscync<Champion>(ApiChampion, champion);
}
*/
/**** Méthodes GET ****/ /**** Méthodes GET ****/
[HttpGet] [HttpGet]
public async Task<ActionResult<ChampionDto>> GetChamps() public async Task<ActionResult<ChampionDto>> GetChamps()
{ {
// Récupération de la liste des champions // Récupération de la liste des champions
IEnumerable<Champion?> Champs = await data.ChampionsMgr.GetItems(0, data.ChampionsMgr.GetNbItems().Result); IEnumerable<Champion?> Champs = await data.ChampionsMgr.GetItems(0, data.ChampionsMgr.GetNbItems().Result);
if (Champs == null)
{
_logger.LogWarning("No chamions found");
return NotFound();
}
// Création de la liste de champion Dto // Création de la liste de champion Dto
List<ChampionDto> DtoChamps = new List<ChampionDto>(); List<ChampionDto> DtoChamps = new List<ChampionDto>();
@ -80,7 +57,6 @@ namespace API.Controllers
} }
} }
[HttpGet("{name}")] [HttpGet("{name}")]
public async Task<ActionResult<ChampionDto>> GetChampByName(string name) public async Task<ActionResult<ChampionDto>> GetChampByName(string name)
{ {
@ -98,7 +74,7 @@ namespace API.Controllers
// Vérification de sa véraciter // Vérification de sa véraciter
if (resultat == null) if (resultat == null)
{ {
_logger.LogWarning("No chamions found with {name}", name); ; _logger.LogWarning("No chamions found with {name}", name);
return NotFound(); return NotFound();
} }
return Ok(resultat); return Ok(resultat);
@ -111,7 +87,6 @@ namespace API.Controllers
} }
/**** Méthodes POST ****/ /**** Méthodes POST ****/
[HttpPost("Ajouter/{nom}")] [HttpPost("Ajouter/{nom}")]
public async Task<ActionResult> PostChampName(string nom) public async Task<ActionResult> PostChampName(string nom)
@ -125,8 +100,11 @@ namespace API.Controllers
return CreatedAtAction(nameof(GetChampByName), new { Id = data.ChampionsMgr.GetNbItemsByName(nom) }, champion.ToDto()); return CreatedAtAction(nameof(GetChampByName), new { Id = data.ChampionsMgr.GetNbItemsByName(nom) }, champion.ToDto());
} }
[HttpPost("Ajouter")] [HttpPost("Ajouter")]
public async Task<ActionResult> PostChamp([FromBody] ChampionDto championDto) public async Task<ActionResult> PostChamp([FromBody] ChampionDto championDto)
{
try
{ {
// Convertie le championDto en model (a était ajouté via l'API) // Convertie le championDto en model (a était ajouté via l'API)
Champion champion = championDto.ToModel(); Champion champion = championDto.ToModel();
@ -134,51 +112,65 @@ namespace API.Controllers
// Ajout du champion en BD // Ajout du champion en BD
await data.ChampionsMgr.AddItem(champion); await data.ChampionsMgr.AddItem(champion);
return CreatedAtAction(nameof(data.ChampionsMgr.GetItemsByName), new { Name = championDto.Name }, championDto); _logger.LogInformation("Sucessfully saved Champions : " + champion.Name);
}
[HttpPost] return CreatedAtAction(nameof(data.ChampionsMgr.GetItemsByName), new { championDto.Name }, championDto);
public async Task<ActionResult> post([FromBody] ChampionDto championDto) }
catch (Exception e)
{ {
return CreatedAtAction(nameof(GetChampByName), new { id = 1 }, await data.ChampionsMgr.AddItem(championDto.ToModel())); _logger.LogError("Somthing goes wrong caching the Champions controller : " + e.Message);
return BadRequest(e.Message);
}
} }
/**** Méthodes DELETE ****/ /**** Méthodes DELETE ****/
[HttpDelete("Supprimer/{id}")] [HttpDelete("Supprimer/{name}")]
public async Task<IActionResult> DeleteChamp(int id) public async Task<IActionResult> DeleteChamp(string name)
{ {
IEnumerable<Champion?> lcha = await data.ChampionsMgr.GetItems(id, 1); try
{
_logger.LogInformation("Executing {Action} with name : {championName}", nameof(DeleteChamp), name);
var champion = await data.ChampionsMgr.GetItemsByName(name, 0, await data.ChampionsMgr.GetNbItems());
if (id >= 0 && id < data.ChampionsMgr.GetNbItems().Result) if (champion != null) await data.ChampionsMgr.DeleteItem(champion.First());
else
{ {
Champion ca = lcha.First(); _logger.LogError($"No chamions found with {name} cannot delete"); ;
data.ChampionsMgr.DeleteItem(ca); return NotFound($"No chamions found with {name} cannot delete");
}
return Ok(); return Ok();
} }
return BadRequest(); catch (Exception e)
{
_logger.LogError("Somthing goes wrong caching the Champions controller : " + e.Message);
return BadRequest(e.Message);
}
} }
/**** Méthodes PUT ****/
/**** Méthodes PUT **** [HttpPut("Modifier/{name}")]
public async Task<ActionResult> PutChampName(string name, [FromBody] ChampionDto value)
[HttpPut("Modifier/{nom}")]
public async Task<ActionResult> PutChampName(string nom)
{ {
Champion champion = new Champion(nom); try
{
await data.ChampionsMgr.AddItem(champion); _logger.LogInformation("Executing {Action} with name : {championName}", nameof(PutChampName), name);
var champion = await data.ChampionsMgr.GetItemsByName(name, 0, await data.ChampionsMgr.GetNbItems());
return CreatedAtAction(nameof(GetChampById), new { id = data.ChampionsMgr.GetNbItems().Result - 1 }, champion.ToDto()); if (champion == null)
{
_logger.LogError("No chamions found with {name} in the dataBase", name); ;
return NotFound();
} }
[HttpPut("Modifier")] await data.ChampionsMgr.UpdateItem(champion.First(), value.ToModel());
public async Task<IActionResult> PutChamp([FromBody] ChampionDto championDto) return Ok();
}
catch (Exception e)
{ {
Champion champion = championDto.ToModel(); _logger.LogError("Somthing goes wrong caching the Champions controller : " + e.Message);
await data.ChampionsMgr.UpdateItem(champion); return BadRequest(e.Message);
return CreatedAtAction(nameof(GetChampById), new { id = data.ChampionsMgr.GetItems(0, data.ChampionsMgr.GetNbItems().Result).Result.ToList().IndexOf(champion) }, champion); }
} }
*/
} }
} }

@ -1,6 +1,11 @@
using EFlib; using EFlib;
using EFManager; using EFManager;
using FluentAssertions.Common;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Versioning;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.OpenApi.Models;
using Model; using Model;
using StubLib; using StubLib;
@ -9,17 +14,41 @@ var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("SQLiteContext"); var connectionString = builder.Configuration.GetConnectionString("SQLiteContext");
builder.Services.AddDbContext<SQLiteContext>(options => options.UseSqlite(connectionString), ServiceLifetime.Singleton); builder.Services.AddDbContext<SQLiteContext>(options => options.UseSqlite(connectionString), ServiceLifetime.Singleton);
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSingleton<ManagerData>(); builder.Services.AddSingleton<ManagerData>();
builder.Services.AddScoped<StubData>(); builder.Services.AddScoped<StubData>();
// builder.Services.AddScoped<ManagerData>(); // builder.Services.AddScoped<ManagerData>();
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
//builder.Services.AddSwaggerGen();
builder.Services.AddVersionedApiExplorer(setup =>
{
setup.GroupNameFormat = "'v'VVV";
setup.SubstituteApiVersionInUrl = true;
});
// Versionnage
builder.Services.AddApiVersioning(opt =>
{
opt.DefaultApiVersion = new ApiVersion(1, 0);
opt.AssumeDefaultVersionWhenUnspecified = true;
opt.ReportApiVersions = true;
opt.ApiVersionReader = ApiVersionReader.Combine(new UrlSegmentApiVersionReader());
});
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "API v1", Version = "v1" });
options.SwaggerDoc("v2", new OpenApiInfo { Title = "API v2", Version = "v2" });
options.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
});
var app = builder.Build(); var app = builder.Build();
var apiVersionDescriptionProvider = app.Services.GetRequiredService<IApiVersionDescriptionProvider>();
app?.Services?.GetService<SQLiteContext>()?.Database.EnsureCreated(); app?.Services?.GetService<SQLiteContext>()?.Database.EnsureCreated();
@ -27,8 +56,17 @@ app?.Services?.GetService<SQLiteContext>()?.Database.EnsureCreated();
if (app.Environment.IsDevelopment()) if (app.Environment.IsDevelopment())
{ {
app.UseSwagger(); app.UseSwagger();
app.UseSwaggerUI(); app.UseSwaggerUI(options =>
{
foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions)
{
options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json",
description.GroupName.ToUpperInvariant());
} }
});
}
app.UseApiVersioning();
app.UseHttpsRedirection(); app.UseHttpsRedirection();

Loading…
Cancel
Save