Merge remote-tracking branch 'origin/main' into j3/feat/pagination
This commit is contained in:
@@ -3,7 +3,7 @@ name: Deploiement API Prod Docker
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- dev
|
- main
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy:
|
deploy:
|
||||||
|
|||||||
@@ -20,4 +20,4 @@ RUN dotnet publish "./Webzine.WebApplication.csproj" -c $BUILD_CONFIGURATION -o
|
|||||||
FROM base AS final
|
FROM base AS final
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=publish /app/publish .
|
COPY --from=publish /app/publish .
|
||||||
ENTRYPOINT ["dotnet", "Webzine.WebApplication.dll"]
|
ENTRYPOINT ["dotnet", "Webzine.WebApplication.dll", "--seed"]
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
using Npgsql;
|
||||||
|
|
||||||
using Webzine.EntitiesContext;
|
using Webzine.EntitiesContext;
|
||||||
using Webzine.Entity;
|
using Webzine.Entity;
|
||||||
using Webzine.Repository.Contracts;
|
using Webzine.Repository.Contracts;
|
||||||
@@ -38,7 +40,19 @@ public class DbCommentaireRepository : ICommentaireRepository
|
|||||||
}
|
}
|
||||||
catch (DbUpdateException dbex)
|
catch (DbUpdateException dbex)
|
||||||
{
|
{
|
||||||
this.logger.LogError(dbex, "Erreur de base de données lors de l'ajout du commentaire de l'auteur : {Auteur}", commentaire?.Auteur);
|
PostgresException? postgresException = dbex.InnerException as PostgresException;
|
||||||
|
|
||||||
|
this.logger.LogError(
|
||||||
|
dbex,
|
||||||
|
"Erreur de base de données lors de l'ajout du commentaire. Auteur: {Auteur} | IdTitre: {IdTitre} | DateCreation: {DateCreation:o} | PostgresCode: {PostgresCode} | Detail: {Detail} | Constraint: {Constraint} | Column: {Column} | Table: {Table}",
|
||||||
|
commentaire?.Auteur,
|
||||||
|
commentaire?.IdTitre,
|
||||||
|
commentaire?.DateCreation,
|
||||||
|
postgresException?.SqlState,
|
||||||
|
postgresException?.Detail,
|
||||||
|
postgresException?.ConstraintName,
|
||||||
|
postgresException?.ColumnName,
|
||||||
|
postgresException?.TableName);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -421,7 +421,8 @@ public class DbTitreRepository : ITitreRepository
|
|||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.OrderByDescending(t => t.DateCreation)
|
.OrderByDescending(t => t.DateCreation)
|
||||||
.Paginate(offset, limit)
|
.Paginate(offset, limit)
|
||||||
.Include(t => t.Artiste);
|
.Include(t => t.Artiste)
|
||||||
|
.Include(a => a.Styles);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,16 +20,23 @@ namespace Webzine.WebApplication.Controllers
|
|||||||
private readonly ILogger<TitreController> logger;
|
private readonly ILogger<TitreController> logger;
|
||||||
private readonly ITitreRepository titreRepository;
|
private readonly ITitreRepository titreRepository;
|
||||||
|
|
||||||
|
// Pour les commentaires.
|
||||||
|
private readonly ICommentaireRepository commentaireRepository;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="TitreController"/> class.
|
/// Initializes a new instance of the <see cref="TitreController"/> class.
|
||||||
/// Initialise une nouvelle instance de la classe <see cref="TitreController"/>.
|
/// Initialise une nouvelle instance de la classe <see cref="TitreController"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="logger">Service de journalisation injecte.</param>
|
/// <param name="logger">Service de journalisation injecte.</param>
|
||||||
/// <param name="titreRepository">Repository des titres injecte.</param>
|
/// <param name="titreRepository">Repository des titres injecte.</param>
|
||||||
public TitreController(ILogger<TitreController> logger, ITitreRepository titreRepository)
|
public TitreController(
|
||||||
|
ILogger<TitreController> logger,
|
||||||
|
ITitreRepository titreRepository,
|
||||||
|
ICommentaireRepository commentaireRepository)
|
||||||
{
|
{
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.titreRepository = titreRepository;
|
this.titreRepository = titreRepository;
|
||||||
|
this.commentaireRepository = commentaireRepository;
|
||||||
|
|
||||||
this.logger.LogInformation("Initialisation du controleur TitreController.");
|
this.logger.LogInformation("Initialisation du controleur TitreController.");
|
||||||
}
|
}
|
||||||
@@ -101,31 +108,30 @@ namespace Webzine.WebApplication.Controllers
|
|||||||
[HttpPost]
|
[HttpPost]
|
||||||
public IActionResult Comment([Bind(Prefix = "CommentForm")] TitreComment model)
|
public IActionResult Comment([Bind(Prefix = "CommentForm")] TitreComment model)
|
||||||
{
|
{
|
||||||
|
var titreToUpdate = this.titreRepository.Find(model.IdTitre);
|
||||||
|
|
||||||
if (!this.ModelState.IsValid)
|
if (!this.ModelState.IsValid)
|
||||||
{
|
{
|
||||||
var titre = this.titreRepository.Find(model.IdTitre);
|
if (titreToUpdate == null)
|
||||||
if (titre == null)
|
|
||||||
{
|
{
|
||||||
this.logger.LogWarning("Titre avec ID {Id} introuvable pour ajout de commentaire.", model.IdTitre);
|
this.logger.LogWarning("Titre avec ID {Id} introuvable pour ajout de commentaire.", model.IdTitre);
|
||||||
return this.RedirectToAction("Index", "Accueil");
|
return this.RedirectToAction("Index", "Accueil");
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.View("Index", this.BuildTitreDetailViewModel(titre, model));
|
return this.View("Index", this.BuildTitreDetailViewModel(titreToUpdate, model));
|
||||||
}
|
}
|
||||||
|
|
||||||
var titreToUpdate = this.titreRepository.Find(model.IdTitre);
|
|
||||||
if (titreToUpdate != null)
|
if (titreToUpdate != null)
|
||||||
{
|
{
|
||||||
var commentaire = new Commentaire
|
var commentaire = new Commentaire
|
||||||
{
|
{
|
||||||
Auteur = model.Auteur,
|
Auteur = model.Auteur,
|
||||||
Contenu = model.Contenu,
|
Contenu = model.Contenu,
|
||||||
DateCreation = DateTime.Now,
|
DateCreation = DateTime.UtcNow,
|
||||||
IdTitre = model.IdTitre,
|
IdTitre = model.IdTitre,
|
||||||
};
|
};
|
||||||
|
|
||||||
titreToUpdate.Commentaires.Add(commentaire);
|
this.commentaireRepository.Add(commentaire);
|
||||||
this.titreRepository.Update(titreToUpdate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.RedirectToAction("Index", new { id = model.IdTitre });
|
return this.RedirectToAction("Index", new { id = model.IdTitre });
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Filtre d'exception global qui intercepte toute exception non gérée et la journalise automatiquement.
|
/// Filtre d'exception global qui intercepte toute exception non geree et la journalise automatiquement.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GlobalExceptionFilter : IExceptionFilter
|
public class GlobalExceptionFilter : IExceptionFilter
|
||||||
{
|
{
|
||||||
@@ -13,7 +13,7 @@ public class GlobalExceptionFilter : IExceptionFilter
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="GlobalExceptionFilter"/> class.
|
/// Initializes a new instance of the <see cref="GlobalExceptionFilter"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="logger">Service de journalisation injecté.</param>
|
/// <param name="logger">Service de journalisation injecte.</param>
|
||||||
public GlobalExceptionFilter(ILogger<GlobalExceptionFilter> logger)
|
public GlobalExceptionFilter(ILogger<GlobalExceptionFilter> logger)
|
||||||
{
|
{
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
@@ -22,11 +22,14 @@ public class GlobalExceptionFilter : IExceptionFilter
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void OnException(ExceptionContext context)
|
public void OnException(ExceptionContext context)
|
||||||
{
|
{
|
||||||
|
string detail = BuildExceptionDetail(context.Exception);
|
||||||
|
|
||||||
this.logger.LogError(
|
this.logger.LogError(
|
||||||
context.Exception,
|
context.Exception,
|
||||||
"Erreur non gérée dans {Action} : {Message}",
|
"Erreur non geree dans {Action} : {Message} | Details: {Details}",
|
||||||
context.ActionDescriptor.DisplayName,
|
context.ActionDescriptor.DisplayName,
|
||||||
context.Exception.Message);
|
context.Exception.Message,
|
||||||
|
detail);
|
||||||
|
|
||||||
context.Result = new ObjectResult(new
|
context.Result = new ObjectResult(new
|
||||||
{
|
{
|
||||||
@@ -39,4 +42,18 @@ public class GlobalExceptionFilter : IExceptionFilter
|
|||||||
|
|
||||||
context.ExceptionHandled = true;
|
context.ExceptionHandled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string BuildExceptionDetail(Exception exception)
|
||||||
|
{
|
||||||
|
var messages = new List<string>();
|
||||||
|
Exception? current = exception;
|
||||||
|
|
||||||
|
while (current != null)
|
||||||
|
{
|
||||||
|
messages.Add($"{current.GetType().Name}: {current.Message}");
|
||||||
|
current = current.InnerException;
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Join(" --> ", messages);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"Seeder": "Local",
|
"Seeder": "Spotify",
|
||||||
"Repository": "Db",
|
"Repository": "Db",
|
||||||
"SpotifySeeder": {
|
"SpotifySeeder": {
|
||||||
"ClientId": "",
|
"ClientId": "390689c2fc79408b830d2f518375ef84",
|
||||||
"ClientSecret": ""
|
"ClientSecret": "6e98a09c77ad43ae93bc0f0560cfcbe1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user