From 1f849af88644719ee2efc6570bc0c3c27a4a43c9 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sat, 19 Sep 2026 21:46:08 +0100 Subject: [PATCH] refacto publication --- .vscode/tasks.json | 20 +++------------ src/Yavsc.Blogs.Tests/BlogAclApiTests.cs | 6 ++--- src/Yavsc.Server/Models/Blog/BlogPost.cs | 6 ++--- src/Yavsc.Server/Services/BlogSpotService.cs | 27 +++++--------------- 4 files changed, 16 insertions(+), 43 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 71384cd8c..cbd3a744d 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,27 +1,13 @@ { "version": "2.0.0", "isRoot": true, - "problemMatcher": [ - { - "owner": "dotnet", - "fileLocation": ["relative", "${workspaceFolder}"], - "source": "dotnet", - "pattern": { - "regexp": "^\\s*(.*)\\((\\d+),(\\d+)\\):\\s+(error|warning) (.*)$", - "file": 1, - "line": 2, - "column": 3, - "severity": 4, - "code": 5, - "message": 6 - } - } - ], + "tasks": [ { "label": "run-debug-android", "command": "dotnet", "type": "shell", + "problemMatcher": ["$msCompile"], "options": { "cwd": "${workspaceFolder}/src/PostIt/PostIt.Android", "env": { @@ -43,6 +29,7 @@ "label": "build", "command": "dotnet", "type": "process", + "problemMatcher": ["$msCompile"], "args": ["build", "/property:GenerateFullPaths=true"], "group": "build", "isBuildCommand": true, @@ -109,6 +96,7 @@ "isTestCommand": false, "isBackground": true, "command": "dotnet", + "problemMatcher": ["$msCompile"], "args": ["build", "/property:GenerateFullPaths=true"], "options": { "cwd": "src/PostIt/PostIt.Desktop" diff --git a/src/Yavsc.Blogs.Tests/BlogAclApiTests.cs b/src/Yavsc.Blogs.Tests/BlogAclApiTests.cs index 174838173..e47ab4e57 100644 --- a/src/Yavsc.Blogs.Tests/BlogAclApiTests.cs +++ b/src/Yavsc.Blogs.Tests/BlogAclApiTests.cs @@ -13,7 +13,7 @@ using static Yavsc.Constants; namespace Yavsc.Blogs.Tests; /// -/// Behavioural tests for BlogAclApiController.PostCircleAuthorizationToBlogPost: +/// Behavioral tests for BlogAclApiController.PostCircleAuthorizationToBlogPost: /// POST /api/v1/blogacl with a JSON body of /// CircleAuthorizationToBlogPost (CircleId + BlogPostId). /// @@ -84,7 +84,7 @@ public sealed class BlogAclApiTests : IClassFixture // rather than being rewritten to ClaimTypes.NameIdentifier. // The controller, however, reads the user id via // User.FindFirstValue(ClaimTypes.NameIdentifier), so we add - // an explicit nameid claim to keep the legacy lookup happy. + // an explicit NameIdentifier claim to keep the legacy lookup happy. http.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue( "Bearer", @@ -106,7 +106,7 @@ public sealed class BlogAclApiTests : IClassFixture /// when POSTs the /// shape { "circleId": <id> } — the exact body the /// PostIt client builds from - /// (which only carries CircleId). The server deserialises + /// (which only carries CircleId). The server deserializes /// it into , leaves /// BlogPostId at its default(long) = 0, attaches /// no Target navigation, and EF Core refuses to INSERT diff --git a/src/Yavsc.Server/Models/Blog/BlogPost.cs b/src/Yavsc.Server/Models/Blog/BlogPost.cs index 25caacb78..d948e8880 100644 --- a/src/Yavsc.Server/Models/Blog/BlogPost.cs +++ b/src/Yavsc.Server/Models/Blog/BlogPost.cs @@ -57,7 +57,7 @@ namespace Yavsc.Models.Blog get; set; } - [Display(Name = "Utilisateur ayant modifé le dernier")] + [Display(Name = "Utilisateur ayant modifié le dernier")] public string? UserModified { get; set; @@ -106,10 +106,10 @@ namespace Yavsc.Models.Blog /// [NotMapped] so no migration is needed. The /// service hydrates it after each fetch (single bulk /// lookup, not N+1) and it surfaces through the wire - /// as part of the JSON-serialised BlogPost. + /// as part of the JSON-serialized BlogPost. /// [NotMapped] - public bool IsPublished { get; set; } + public bool IsPublished { get => Publication != null; } [JsonIgnore] /// diff --git a/src/Yavsc.Server/Services/BlogSpotService.cs b/src/Yavsc.Server/Services/BlogSpotService.cs index 6ad1fb112..bd182c437 100644 --- a/src/Yavsc.Server/Services/BlogSpotService.cs +++ b/src/Yavsc.Server/Services/BlogSpotService.cs @@ -108,7 +108,7 @@ public class BlogSpotService public BlogPost Create(string userId, BlogPost post ) { // Sauvegarder le post d'abord pour obtenir son ID - // Le createur vient de l'authentification, donc on ne le prend pas du post + // Le créateur vient de l'authentification, donc on ne le prend pas du post post.AuthorId = userId; _context.BlogSpot.Add(post); _context.SaveChanges(userId); @@ -139,15 +139,12 @@ public class BlogSpotService .Include(p => p.Tags) .Include(p => p.Comments) .Include(p => p.ACL) + .Include(p => p.Publication) .SingleAsync(m => m.Id == blogPostId); if (blog == null) return null; - // Hydrate le flag [NotMapped] depuis la table de publication. - blog.IsPublished = await _context.blogSpotPublications - .AnyAsync(pub => pub.PostId == blogPostId); - var auth = await _authorizationService.AuthorizeAsync(user, blog, new ReadPermission()); if (!auth.Succeeded) throw new AuthorizationFailureException(auth); @@ -233,6 +230,7 @@ public class BlogSpotService .Include(p => p.Comments) .Include(p => p.Publication) .Where(p => p.Publication != null + || p.AuthorId == viewerId || (userCircles != null && p.ACL.Any(a => userCircles.Contains(a.CircleId)))); } else @@ -247,25 +245,12 @@ public class BlogSpotService .ToArray(); } - var materialised = posts.ToList(); + var materialized = posts.ToList(); - var postIds = materialised.Select(p => p.Id).ToList(); - if (postIds.Count > 0) - { - var publishedIds = await _context.blogSpotPublications - .Where(pub => postIds.Contains(pub.PostId)) - .Select(pub => pub.PostId) - .ToListAsync(); - - var publishedSet = publishedIds.ToHashSet(); - foreach (var post in materialised.OfType()) - post.IsPublished = publishedSet.Contains(post.Id); - } - - foreach (var post in materialised.OfType()) + foreach (var post in materialized.OfType()) ScrubAclForViewer(post, user); - return materialised + return materialized .OrderByDescending(p => p.DateModified) .Skip(skip) .Take(take);