feat(domain): introduce PostAuthor value object for blog post authorship (#296)#298
Conversation
🏗️ PR Added to Squad Triage QueueThis PR has been labeled with Next steps:
|
There was a problem hiding this comment.
Pull request overview
This PR introduces a structured PostAuthor value object and threads it through the domain, persistence, DTO mapping, validators, UI, and tests to support capturing richer authorship data on blog posts (Issue #296).
Changes:
- Added
PostAuthorvalue object and updatedBlogPost.AuthorfromstringtoPostAuthor, including creation guards. - Updated MongoDB EF Core mapping (
OwnsOne) and web DTO/mapping to flatten author fields (AuthorId,AuthorName,AuthorEmail,AuthorRoles). - Updated create flow command/validation and adjusted unit/integration/bUnit tests for the new author model.
Reviewed changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Web.Tests/Infrastructure/Caching/BlogPostCacheServiceTests.cs | Updated cached DTO construction to new flattened author DTO shape. |
| tests/Web.Tests/Handlers/GetBlogPostsHandlerTests.cs | Updated handler tests to construct BlogPost with PostAuthor and updated DTOs. |
| tests/Web.Tests/Handlers/EditBlogPostHandlerTests.cs | Updated handler tests for new BlogPost.Create signature and DTO shape. |
| tests/Web.Tests/Handlers/CreateBlogPostHandlerTests.cs | Updated create handler tests to pass PostAuthor into the command. |
| tests/Web.Tests/GlobalUsings.cs | Added MyBlog.Domain.ValueObjects global using for tests. |
| tests/Web.Tests/Features/BlogPosts/Commands/CreateBlogPostDomainCommandValidatorTests.cs | Updated validation tests for PostAuthor (null + name validation). |
| tests/Web.Tests/Features/BlogPosts/Commands/CreateBlogPostCommandValidatorTests.cs | Updated validator tests for PostAuthor fields and property paths. |
| tests/Web.Tests/Data/BlogPostMappingsTests.cs | Updated mapping assertions to verify flattened author DTO fields. |
| tests/Web.Tests/BlogPostTests.cs | Updated entity unit tests for PostAuthor and new author guards. |
| tests/Web.Tests/Behaviors/ValidationBehaviorTests.cs | Updated pipeline tests to use PostAuthor in commands. |
| tests/Web.Tests.Integration/GlobalUsings.cs | Added MyBlog.Domain.ValueObjects global using for integration tests. |
| tests/Web.Tests.Integration/Caching/BlogPostCacheServiceTests.cs | Updated integration cache DTO construction for flattened author fields. |
| tests/Web.Tests.Integration/BlogPosts/MongoDbBlogPostRepositoryTests.cs | Updated integration repo tests to persist/load PostAuthor instead of string author. |
| tests/Web.Tests.Bunit/GlobalUsings.cs | Added MyBlog.Domain.ValueObjects global using for bUnit tests. |
| tests/Web.Tests.Bunit/Components/RazorSmokeTests.cs | Updated UI smoke tests for new DTO shape and command author object. |
| tests/Domain.Tests/GlobalUsings.cs | Added MyBlog.Domain.ValueObjects global using for domain tests. |
| tests/Domain.Tests/Entities/BlogPostTests.cs | Updated domain entity tests for PostAuthor and new guards. |
| src/Web/Features/BlogPosts/List/Index.razor | Updated list UI to display AuthorName instead of prior Author string. |
| src/Web/Features/BlogPosts/Create/CreateBlogPostCommandValidator.cs | Updated validator to validate PostAuthor presence and Author.Name. |
| src/Web/Features/BlogPosts/Create/CreateBlogPostCommand.cs | Updated command contract to use PostAuthor instead of string. |
| src/Web/Features/BlogPosts/Create/Create.razor | Updated submit handler to construct a PostAuthor for the create command. |
| src/Web/Data/BlogPostMappings.cs | Updated mapping to flatten PostAuthor into BlogPostDto. |
| src/Web/Data/BlogPostDto.cs | Updated DTO contract to carry flattened author identity fields and roles. |
| src/Web/Data/BlogDbContext.cs | Added OwnsOne mapping for BlogPost.Author as an embedded MongoDB document. |
| src/Domain/ValueObjects/PostAuthor.cs | Added new PostAuthor value object record (Id/Name/Email/Roles + Empty). |
| src/Domain/Entities/BlogPost.cs | Updated domain entity to store PostAuthor and enforce author null/name guards. |
| .WithMessage("Author is required."); | ||
| RuleFor(x => x.Author.Name) | ||
| .NotEmpty() | ||
| .WithMessage("Author name is required.") |
| public sealed record PostAuthor( | ||
| string Id, | ||
| string Name, | ||
| string Email, | ||
| IReadOnlyList<string> Roles) |
| var author = new PostAuthor(string.Empty, _model.Author, string.Empty, []); | ||
| var result = await Sender.Send(new CreateBlogPostCommand(_model.Title, _model.Content, author)); |
Test Results Summary354 tests - 2 353 ✅ - 2 19s ⏱️ ±0s Results for commit fb9db3c. ± Comparison against base commit 4b5d0d2. This pull request removes 15 and adds 13 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
|
Triage: ✅ Routed to Sam (Backend Developer) This PR implements PostAuthor value object per feature #296. The PR body correctly identifies the work as backend domain (Domain, Infrastructure, DTO, Command/Validation, Tests). Sam will own implementation. Note for Legolas: UI stub in Create.razor still needs AuthenticationStateProvider injection to auto-populate PostAuthor from auth claims. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## dev #298 +/- ##
==========================================
+ Coverage 82.80% 83.08% +0.28%
==========================================
Files 46 47 +1
Lines 1192 1230 +38
Branches 145 148 +3
==========================================
+ Hits 987 1022 +35
Misses 147 147
- Partials 58 61 +3
🚀 New features to boost your workflow:
|
…hip (#296) - Add PostAuthor sealed record (Id, Name, Email, Roles) with PostAuthor.Empty helper - Replace string Author with PostAuthor on BlogPost entity and Create() factory - Update BlogDbContext with OwnsOne mapping for PostAuthor sub-document - Flatten PostAuthor fields in BlogPostDto (AuthorId, AuthorName, AuthorEmail, AuthorRoles) - Update BlogPostMappings.ToDto() for new flat DTO shape - Update CreateBlogPostCommand to carry PostAuthor; update FluentValidation rules - Add temporary stub in Create.razor (Legolas to inject AuthenticationStateProvider) - Update Index.razor to use @post.AuthorName - Update all test projects for new types and constructor signatures BREAKING: Existing MongoDB docs with 'Author' string field must be migrated. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
#296) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove manual Author input from Create.razor. Inject AuthenticationStateProvider
and populate PostAuthor from the logged-in user's claims (sub, name, email, roles)
in OnInitializedAsync. Pass PostAuthor to CreateBlogPostCommand in HandleSubmit.
Show read-only "Author: {name}" display above the form for transparency.
Uses RoleClaimsHelper.GetRoles() consistent with Profile.razor pattern.
Add TestAuthenticationStateProvider to bUnit test support so Create component
tests can resolve the injected AuthenticationStateProvider. Update RazorSmokeTests
to register it in DI, set the user in RenderWithUser, and remove stale assertions
that assumed an Author input field.
Closes #296
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
aa66e0a to
fb9db3c
Compare
Summary
Implements Issue #296 — auto-fill Author when creating a new blog post.
Closes #296
Working as Sam (Backend Developer)
Changes
PostAuthorsealed record inMyBlog.Domain.ValueObjects(Id, Name, Email, Roles +PostAuthor.Emptyhelper)BlogPost.Authorchanged fromstringtoPostAuthor;Create()guards null author and empty NameBlogDbContextusesOwnsOneto map PostAuthor as a MongoDB sub-documentBlogPostDtoflattens PostAuthor toAuthorId,AuthorName,AuthorEmail,AuthorRolesCreateBlogPostCommand.Authoris nowPostAuthor; validator checks NotNull + Name.NotEmptyCreate.razorhas a temporary placeholder constructingPostAuthorfrom a form field — Legolas needs to replace this withAuthenticationStateProviderinjectionBreaking Change
Existing MongoDB documents with
"Author": "string"will fail to deserialize. Dev: drop/recreate collection. Prod: migration script needed (out of scope Sprint 19).Notes for Legolas
Create.razorstill has anAuthortext input as a placeholder. The next step is to injectAuthenticationStateProvider, read claims (NameIdentifier, Name, Email, roles), and buildPostAuthorautomatically — removing the manual input field.