release/1.0.8-rc1 #42
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "release/1.0.8-rc1"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
System.Text.Json cannot materialise an interface without a polymorphic converter. Until this commit, BlogPostDto.Author was typed as the abstract interface IApplicationUser, which crashed the "load posts" call in PostIt whenever the server returned a post with a populated Author object (the common case — GET /api/BlogApi). Fix: * Introduce a minimum-viable wire DTO BlogPostAuthorDto in Yavsc.Abstract.Blogspot (record: Id, UserName, Avatar). These are the only fields the client UI actually needs; the server-side ApplicationUser navigation is preserved for permission checks and authorisation. * Change IBlogPost.Author and BlogPostDto.Author from IApplicationUser to BlogPostAuthorDto? (interface change, breaking). The EF entity BlogPost keeps its full ApplicationUser navigation property and exposes IBlogPost.Author via an explicit interface implementation that projects to BlogPostAuthorDto on demand (so EF can still lazy-load the navigation without forcing an eager join on every read). * Restore the using directive that was accidentally removed when the BlogPostDto property was rewritten (needed for ICircleAuthorization in GetACL()). Regression coverage (the missing test Paul flagged): * Add BlogPostAuthorDtoTests in PostIt.Tests with four scenarios that exercise the wire shape on the client side: - A BlogPostDto JSON with a populated Author round-trips through JsonSerializer without throwing and the three fields (Id, UserName, Avatar) survive intact. - A BlogPostDto JSON with explicit "author": null deserialises with Author == null. - A BlogPostDto JSON without any Author field at all deserialises with Author == null (forward compat). - The serialised shape of BlogPostAuthorDto uses camelCase property names (matching the server's Web defaults), so the field names on the wire don't drift without a test catching it. Tests: 55/55 PostIt.Tests (+4 new), 24/24 Yavsc.Blogs.Tests, 44/44 Yavsc.Org.Tests. No regressions. Side note: yavsc.sln picks up Yavsc.Api.Client (added by 'feat/postit-acl' in 1.0.7 but never registered in the solution file until now — probably auto-added by a recent 'dotnet build' that discovered the .csproj).The bool Comment on CircleAuthorizationToBlogPost was dead code: never read or written by any caller in src/, no UI exposure, no behavioural semantics. The wire DTO (CircleAuthorization in Yavsc.Abstract) doesn't carry it, no reader consumes it, and the PostIt client builds its payload without it. What changes: - src/Yavsc.Server/Models/Access/CircleAuthorizationToBlogPost.cs: remove the property. - src/Yavsc.Blogs.Tests/BlogAclApiTests.cs: drop 'Comment = true' from the existing test payload and trim the now-inaccurate XML doc comment ('CircleId + BlogPostId + Comment' -> 'CircleId + BlogPostId'). Also adds a new [Fact] pinning the prod bug reported on 2026-08-21 (HTTP 500 'BlogPostId is unknown' when PostIt POSTs the bare { circleId } shape). That test stays red: the real fix for the 500 is in PostIt (payload needs blogPostId) + on the wire DTO + server-side validation, and lives in a follow-up commit. Migration: - src/Yavsc.Org/Migrations/20260820232152_DropCommentFromCircleAuthorizationToBlogPost drops the boolean 'Comment' column on CircleAuthorizationToBlogPost. The generated scaffold also wanted to drop three 'ClientId1' shadow FK columns on ClientScopes / ClientRedirectUris / ClientGrantTypes (from leftover HasOne<Client>() overrides in ApplicationDbContext.OnModelCreating); those were removed from the .cs to keep the migration scoped to this fix. Cleaning up the shadow property declarations themselves is left as a separate task. The ModelSnapshot still reflects the shadow 'ClientId1' columns intentionally: they exist in the prod database today (all NULL), and EF will rescaffold a drop migration for them on the next 'migrations add' regardless. No data loss.The hard rule on POST /api/v1/blogacl is: a 500 is never acceptable, regardless of the payload shape. The prod 500 logged on 2026-08-21 on mercure was caused by the PostIt client sending { circleId } only, which the server deserialised into CircleAuthorizationToBlogPost with BlogPostId = default(long) = 0; EF Core refused the INSERT with InvalidOperationException: The value of 'CircleAuthorizationToBlogPost.BlogPostId' is unknown. The PostIt fix lives inb82b6722(enrich the payload with blogPostId). The server-side guard lives in this commit: - BlogAclApiController.CheckOwner is now async and uses FirstOrDefaultAsync instead of First, so it does not deadlock the request thread and returns false on a missing circle (which the controller already maps to ChallengeResult). - BlogsWebServerFixture now seeds Alice, her Circle and her BlogPost in ConfigurePipelineAsync, once at host startup, against the shared SqliteConnection (Cache=Shared). EnsureCreated is idempotent and runs against the connection that every DbContext resolves through, so the test theory can POST payloads with real FK ids against a schema that actually has the Circle / BlogSpot tables. - BlogAclApiTests: - PostCircleAuthorization_returns_201_when_payload_mirrors_PostIt_shape is the regression sentinel for the prod fix. - PostCircleAuthorization_never_returns_500 is a [Theory] over several payload shapes; any future commit that reintroduces a 500 path turns it red. CleanupAcl at the start of each insert- bearing test isolates against xUnit's no-guarantee-of-order execution: a successful POST in test N would otherwise conflict with test N+1 against the same (CircleId, BlogPostId) pair.The 2026-08-21 prod 500 on POST /api/v1/blogacl was caused by the PostIt client sending { circleId } only — the server deserialised into CircleAuthorizationToBlogPost with BlogPostId = default(long) = 0, and EF Core refused the INSERT with InvalidOperationException. The PostIt-side fix lives inb82b6722(enrich the payload with blogPostId). This commit is the server-side guard: validate BlogPostId > 0 in the controller and return 400 BadRequest instead of letting the request reach SaveChangesAsync. The same shape that crashed on 2026-08-21 now fails fast at the validation layer. Verified by BlogAclApiTests.PostCircleAuthorization_dosent_return_500: sentinel that asserts 'never 500' on a payload with BlogPostId = -1. Previously red (500 from EF Core), now green (400 from the new guard).