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
### API (*24 points*)
- [ ] 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*)
- [ ] Utilisation des fichiers configurations (*1 points*)
- [ ] Versionnage de l'api (avec versionnage de la doc) (*1 point*)
- [ ] Logs (*1 point*)
- [ ] Tests unitaires (*3 point*)
- [X] Mise en place de toutes les opérations CRUD (*4 points*)
- [X] API RESTful (respect des règles de routage, utilisation des bons status code ...) (*2 points*)
- [X] Utilisation des fichiers configurations (*1 points*)
- [X] Versionnage de l'api (avec versionnage de la doc) (*1 point*)
- [X] Logs (*1 point*)
- [X] Tests unitaires (*3 point*)
- [ ] Réalisation du client MAUI et liaison avec l'api (*4 point*)
- [ ] Liaison avec la base de données (*2 point*)
- [ ] Filtrage + Pagination des données (*1 point*)
- [X] Liaison avec la base de données (*2 point*)
- [X] Filtrage + Pagination des données (*1 point*)
- [X] Propreté du code (Vous pouvez vous servir de sonarqube) (*2 point*)
- [X] Dockerisation et Hébergement des API (CodeFirst) (*3 point*)

@ -1,12 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<Version>1.0.0.0</Version>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<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" />
</ItemGroup>

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

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

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

@ -1,50 +1,151 @@
using API.Dto;
using API.Mapping;
using EFManager;
using Microsoft.AspNetCore.Mvc;
using Model;
using StubLib;
namespace API.Controllers
{
[ApiController]
[Route("[controller]")]
public class SkinController
[Route("api/[controller]")]
public class SkinController : ControllerBase
{
private readonly ManagerData data;
// private readonly ManagerData data;
private readonly StubData data;
private readonly ILogger<SkinController> _logger;
public SkinController(ManagerData manager, ILogger<SkinController> logger)
public SkinController(StubData manager, ILogger<SkinController> logger)
{
data = manager;
_logger = logger;
}
/*
[HttpGet("{Name}/Skins")]
public async Task<ActionResult<SkinDto>> GetSkinsChamp(string name)
/**** Méthodes GET ****/
[HttpGet]
public async Task<ActionResult<SkinDto>> GetSkins()
{
// Récupération de la liste des champions
IEnumerable<Champion?> Champs = await data.ChampionsMgr.GetItemsByName(name, await data.ChampionsMgr.GetNbItemsByName(name), 1);
// 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
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();
// Ajout du champion en BD
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)
{
_logger.LogError("Somthing goes wrong caching the Skins controller : " + e.Message);
return BadRequest(e.Message);
}
}
/**** Méthodes DELETE ****/
[HttpDelete("Supprimer/{name}")]
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());
// Récupération du champion correspondant à l'id
//if (await data.ChampionsMgr.GetNbItemsByName(name).Result)
if (skin != null) await data.SkinsMgr.DeleteItem(skin.First());
else
{
_logger.LogError($"No skins found with {name} cannot delete"); ;
return NotFound($"No skins found with {name} cannot delete");
}
return Ok();
}
catch (Exception e)
{
// Converstion en Champion au lieu de champion IEnumerable
Champion champion = Champs.First();
_logger.LogError("Somthing goes wrong caching the Champions controller : " + e.Message);
return BadRequest(e.Message);
}
}
// Récupération des skin du champion
IEnumerable<Skin?> Skins = await data.SkinsMgr.GetItemsByChampion(champion, 0, data.SkinsMgr.GetNbItemsByChampion(champion).Result);
// Création de la liste de skin
List<SkinDto> skins = new List<SkinDto>();
/**** Méthodes PUT ****/
// Ajout des skins dans la nouvelle liste
Skins.ToList().ForEach(Skin => skins.Add(Skin.ToDto()));
[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();
}
return Ok(skins);
await data.SkinsMgr.UpdateItem(skin.First(), value.ToModel());
return Ok();
}
return BadRequest();
}*/
catch (Exception e)
{
_logger.LogError("Somthing goes wrong caching the Skins controller : " + e.Message);
return BadRequest(e.Message);
}
}
}
}

@ -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.Mapping;
using EFManager;
using Microsoft.AspNetCore.Mvc;
using Model;
using StubLib;
namespace API.Controllers
namespace API.Controllers.version2
{
[ApiController]
[Route("[controller]")]
[ApiVersion("2.0")]
[Route("api/v{version:ApiVersion}/[controller]")]
public class ChampionController : ControllerBase
{
// private readonly ManagerData data;
private readonly StubData data;
private readonly ILogger<ChampionController> _logger;
@ -20,42 +18,21 @@ namespace API.Controllers
public ChampionController(StubData manager, ILogger<ChampionController> logger)
{
data = manager;
_logger = logger;
data = manager;
_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 ****/
[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>();
@ -80,15 +57,14 @@ namespace API.Controllers
}
}
[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);
@ -98,7 +74,7 @@ namespace API.Controllers
// Vérification de sa véraciter
if (resultat == null)
{
_logger.LogWarning("No chamions found with {name}", name); ;
_logger.LogWarning("No chamions found with {name}", name);
return NotFound();
}
return Ok(resultat);
@ -111,7 +87,6 @@ namespace API.Controllers
}
/**** Méthodes POST ****/
[HttpPost("Ajouter/{nom}")]
public async Task<ActionResult> PostChampName(string nom)
@ -125,60 +100,77 @@ namespace API.Controllers
return CreatedAtAction(nameof(GetChampByName), new { Id = data.ChampionsMgr.GetNbItemsByName(nom) }, champion.ToDto());
}
[HttpPost("Ajouter")]
public async Task<ActionResult> PostChamp([FromBody] ChampionDto championDto)
{
// Convertie le championDto en model (a était ajouté via l'API)
Champion champion = championDto.ToModel();
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);
// Ajout du champion en BD
await data.ChampionsMgr.AddItem(champion);
return CreatedAtAction(nameof(data.ChampionsMgr.GetItemsByName), new { Name = championDto.Name }, championDto);
}
_logger.LogInformation("Sucessfully saved Champions : " + champion.Name);
[HttpPost]
public async Task<ActionResult> post([FromBody] ChampionDto championDto)
{
return CreatedAtAction(nameof(GetChampByName), new { id = 1 }, await data.ChampionsMgr.AddItem(championDto.ToModel()));
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/{id}")]
public async Task<IActionResult> DeleteChamp(int id)
[HttpDelete("Supprimer/{name}")]
public async Task<IActionResult> DeleteChamp(string name)
{
IEnumerable<Champion?> lcha = await data.ChampionsMgr.GetItems(id, 1);
if (id >= 0 && id < data.ChampionsMgr.GetNbItems().Result)
try
{
Champion ca = lcha.First();
data.ChampionsMgr.DeleteItem(ca);
_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();
}
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/{nom}")]
public async Task<ActionResult> PutChampName(string nom)
[HttpPut("Modifier/{name}")]
public async Task<ActionResult> PutChampName(string name, [FromBody] ChampionDto value)
{
Champion champion = new Champion(nom);
await data.ChampionsMgr.AddItem(champion);
return CreatedAtAction(nameof(GetChampById), new { id = data.ChampionsMgr.GetNbItems().Result - 1 }, champion.ToDto());
}
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();
}
[HttpPut("Modifier")]
public async Task<IActionResult> PutChamp([FromBody] ChampionDto championDto)
{
Champion champion = championDto.ToModel();
await data.ChampionsMgr.UpdateItem(champion);
return CreatedAtAction(nameof(GetChampById), new { id = data.ChampionsMgr.GetItems(0, data.ChampionsMgr.GetNbItems().Result).Result.ToList().IndexOf(champion) }, champion);
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,6 +1,11 @@
using EFlib;
using EFManager;
using FluentAssertions.Common;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Versioning;
using Microsoft.EntityFrameworkCore;
using Microsoft.OpenApi.Models;
using Model;
using StubLib;
@ -9,17 +14,41 @@ var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("SQLiteContext");
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.AddScoped<StubData>();
// 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 apiVersionDescriptionProvider = app.Services.GetRequiredService<IApiVersionDescriptionProvider>();
app?.Services?.GetService<SQLiteContext>()?.Database.EnsureCreated();
@ -27,9 +56,18 @@ app?.Services?.GetService<SQLiteContext>()?.Database.EnsureCreated();
if (app.Environment.IsDevelopment())
{
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.UseAuthorization();

Loading…
Cancel
Save