From bc6bebea067604fb787f15cee0972adcdc19c0cf Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Fri, 18 Sep 2026 13:38:42 +0100 Subject: [PATCH] post the file --- src/Yavsc.Api/Helpers/RequestHelpers.cs | 2 ++ .../Controllers/BlogApiController.cs | 21 ++++++++++++++-- src/Yavsc.Blogs/Program.cs | 12 ++++++++++ src/Yavsc.Server/Services/BlogSpotService.cs | 24 +++++++++++++++++-- 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/Yavsc.Api/Helpers/RequestHelpers.cs b/src/Yavsc.Api/Helpers/RequestHelpers.cs index d92e765eb..47601f6f5 100644 --- a/src/Yavsc.Api/Helpers/RequestHelpers.cs +++ b/src/Yavsc.Api/Helpers/RequestHelpers.cs @@ -3,8 +3,10 @@ namespace Yavsc.Api.Helpers public static class RequestHelpers { // Check for some apache proxy header, if any +#pragma warning disable CS8632 // L'annotation pour les types référence Nullable doit être utilisée uniquement dans le code au sein d'un contexte d'annotations '#nullable'. public static string? ForwardedFor(this HttpRequest request) { string? host = request.Headers["X-Forwarded-For"]; +#pragma warning restore CS8632 // L'annotation pour les types référence Nullable doit être utilisée uniquement dans le code au sein d'un contexte d'annotations '#nullable'. if (string.IsNullOrEmpty(host)) { host = request.Host.Value; } else { // Using X-Forwarded-For last address diff --git a/src/Yavsc.Blogs/Controllers/BlogApiController.cs b/src/Yavsc.Blogs/Controllers/BlogApiController.cs index 7aaf221e4..eb8430459 100644 --- a/src/Yavsc.Blogs/Controllers/BlogApiController.cs +++ b/src/Yavsc.Blogs/Controllers/BlogApiController.cs @@ -15,10 +15,14 @@ namespace Yavsc.Blogs.Controllers public class BlogApiController : Controller { private readonly BlogSpotService blogSpotService; + private readonly ILogger logger; - public BlogApiController(BlogSpotService blogSpotService) + public BlogApiController( + BlogSpotService blogSpotService, + ILoggerFactory loggerFactory) { this.blogSpotService = blogSpotService; + this.logger = loggerFactory.CreateLogger(); } // GET: api/v1/blogspot @@ -60,6 +64,7 @@ namespace Yavsc.Blogs.Controllers var blog = await ReadBlogRequestAsync(); if (blog is null) { + logger.LogWarning("PUT /api/v1/blogspot/{id} failed to read blog payload from request body or multipart form.", id); return BadRequest(ModelState); } @@ -79,6 +84,7 @@ namespace Yavsc.Blogs.Controllers result.MemberNames.FirstOrDefault() ?? string.Empty, result.ErrorMessage ?? "Invalid value."); } + logger.LogWarning("PUT /api/v1/blogspot/{id} failed validation: {errors}", id, ModelState); return BadRequest(ModelState); } @@ -107,16 +113,27 @@ namespace Yavsc.Blogs.Controllers var existing = await blogSpotService.GetBlogPostAsync(id); if (existing == null) { + logger.LogWarning("PUT /api/v1/blogspot/{id} failed: blog post not found.", id); return NotFound(); } try { await blogSpotService.Modify(User, blog); - blogSpotService.AttachFiles(files, User.GetUserId(), id); + logger.LogInformation("PUT /api/v1/blogspot/{id} modified successfully.", id); + if (files.Count > 0) + { + logger.LogInformation("PUT /api/v1/blogspot/{id} attaching {fileCount} files.", id, files.Count); + blogSpotService.AttachFiles(files, User.GetUserId(), id); + } + else + { + logger.LogInformation("PUT /api/v1/blogspot/{id} no files to attach.", id); + } } catch (AuthorizationFailureException) { + logger.LogWarning("PUT /api/v1/blogspot/{id} failed: authorization failure.", id); return Challenge(); } diff --git a/src/Yavsc.Blogs/Program.cs b/src/Yavsc.Blogs/Program.cs index 00ac7f6fe..d3d094294 100644 --- a/src/Yavsc.Blogs/Program.cs +++ b/src/Yavsc.Blogs/Program.cs @@ -9,6 +9,7 @@ using Yavsc.Models; using Yavsc.Services; using Yavsc.Server.Helpers; using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; namespace Yavsc.Blogs; internal class Program @@ -22,6 +23,8 @@ internal class Program var services = builder.Services; + var siteSection = builder.Configuration.GetSection("Site"); + services.Configure(siteSection); // MvcBuilder builder.Services .AddAuthorization(options => @@ -79,8 +82,17 @@ internal class Program options.SetDefaultCulture(supportedCultures[0]) .AddSupportedCultures(supportedCultures) .AddSupportedUICultures(supportedCultures); + }) + .Configure(settings => + { + if (settings.Blog == null) + { + settings.Blog = "blog"; + } }); + + // App startup using (var app = builder.Build()) { diff --git a/src/Yavsc.Server/Services/BlogSpotService.cs b/src/Yavsc.Server/Services/BlogSpotService.cs index a0507ffe0..b4bf4c7ad 100644 --- a/src/Yavsc.Server/Services/BlogSpotService.cs +++ b/src/Yavsc.Server/Services/BlogSpotService.cs @@ -5,6 +5,7 @@ using System.Security.Claims; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Yavsc; using Yavsc.Blogspot; @@ -22,17 +23,24 @@ public class BlogSpotService private readonly IAuthorizationService _authorizationService; private readonly IFileSystemAuthManager fileSystemAuthManager; private readonly SiteSettings siteSettings; + private readonly ILogger logger; public BlogSpotService( ApplicationDbContext context, IAuthorizationService authorizationService, IFileSystemAuthManager fileSystemAuthManager, - IOptions siteSettings) + IOptions siteSettings, + ILoggerFactory loggerFactory) { _authorizationService = authorizationService; _context = context; this.fileSystemAuthManager = fileSystemAuthManager; this.siteSettings = siteSettings.Value; + if (siteSettings.Value.Blog == null) + { + throw new InvalidOperationException("SiteSettings.Blog is not configured."); + } + this.logger = loggerFactory.CreateLogger(); } public void AttachFiles(IFormFileCollection files, string userId, long postId) @@ -52,13 +60,19 @@ public class BlogSpotService user.UserName, blogFilesSubdir); var di = new DirectoryInfo(destDir); - if (!di.Exists) di.Create(); + + if (!di.Exists) + { + logger.LogInformation("Creating directory for blog attachments: {destDir}", destDir); + di.Create(); + } foreach (var formFile in files) { var fileInfo = user.ReceiveUserFile(destDir, formFile); if (fileInfo != null && !fileInfo.QuotaOffense) { + logger.LogInformation("Attached file {fileName} to blog post {postId} for user {userId}.", fileInfo.FileName, postId, userId); var uploadedFile = new UploadedFile { Path = fileInfo.FileName, @@ -74,6 +88,11 @@ public class BlogSpotService FileId = uploadedFile.Id }; _context.BlogAttachedFiles.Add(attachment); + logger.LogInformation("Created BlogAttachedFile entry for file {fileName} and blog post {postId}.", fileInfo.FileName, postId); + } + else + { + logger.LogWarning("Failed to attach file {fileName} to blog post {postId} for user {userId}. Quota offense: {quotaOffense}", formFile.FileName, postId, userId, fileInfo?.QuotaOffense); } } _context.SaveChanges(userId); @@ -81,6 +100,7 @@ public class BlogSpotService catch (Exception ex) { Debug.WriteLine($"Erreur lors du traitement des fichiers : {ex.Message}"); + logger.LogError(ex, "Error while processing attached files for blog post {postId} and user {userId}.", postId, userId); } } }