From 1a46b75c2a937e90227fa82b0d8149f5981f85b6 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 4 Mar 2024 10:17:16 +0000 Subject: [PATCH] update code to latest style --- build/Program.cs | 10 +--- src/Conduit/Domain/Article.cs | 16 +++--- src/Conduit/Domain/ArticleFavorite.cs | 8 +-- src/Conduit/Domain/ArticleTag.cs | 8 +-- src/Conduit/Domain/Comment.cs | 16 +++--- src/Conduit/Domain/FollowedPeople.cs | 8 +-- src/Conduit/Domain/Person.cs | 14 +++--- src/Conduit/Domain/Tag.cs | 4 +- .../Features/Articles/ArticlesController.cs | 48 +++++------------- src/Conduit/Features/Articles/Create.cs | 43 ++++++---------- src/Conduit/Features/Articles/Delete.cs | 14 ++---- src/Conduit/Features/Articles/Details.cs | 10 ++-- src/Conduit/Features/Articles/Edit.cs | 43 +++++----------- src/Conduit/Features/Articles/List.cs | 26 ++++------ .../Features/Comments/CommentsController.cs | 27 +++------- src/Conduit/Features/Comments/Create.cs | 29 ++++------- src/Conduit/Features/Comments/Delete.cs | 14 ++---- src/Conduit/Features/Comments/List.cs | 13 ++--- src/Conduit/Features/Favorites/Add.cs | 31 ++++-------- src/Conduit/Features/Favorites/Delete.cs | 31 ++++-------- .../Features/Favorites/FavoritesController.cs | 22 ++------ src/Conduit/Features/Followers/Add.cs | 40 +++++---------- src/Conduit/Features/Followers/Delete.cs | 40 +++++---------- .../Features/Followers/FollowersController.cs | 21 ++------ src/Conduit/Features/Profiles/Details.cs | 21 ++------ .../Features/Profiles/MappingProfile.cs | 5 +- src/Conduit/Features/Profiles/Profile.cs | 6 +-- .../Features/Profiles/ProfileReader.cs | 29 ++++------- .../Features/Profiles/ProfilesController.cs | 16 ++---- src/Conduit/Features/Tags/List.cs | 13 ++--- src/Conduit/Features/Tags/TagsController.cs | 16 ++---- src/Conduit/Features/Users/Create.cs | 50 ++++++------------- src/Conduit/Features/Users/Details.cs | 34 ++++--------- src/Conduit/Features/Users/Edit.cs | 40 +++++---------- src/Conduit/Features/Users/Login.cs | 39 +++++---------- src/Conduit/Features/Users/MappingProfile.cs | 5 +- src/Conduit/Features/Users/User.cs | 8 +-- src/Conduit/Features/Users/UserController.cs | 27 +++------- src/Conduit/Features/Users/UsersController.cs | 12 ++--- src/Conduit/Infrastructure/ConduitContext.cs | 33 ++++++------ .../Infrastructure/CurrentUserAccessor.cs | 19 ++----- .../DBContextTransactionPipelineBehavior.cs | 16 +++--- .../Errors/ErrorHandlingMiddleware.cs | 35 ++++--------- .../Infrastructure/Errors/RestException.cs | 14 ++---- .../Security/JwtTokenGenerator.cs | 11 ++-- .../ValidationPipelineBehavior.cs | 9 ++-- src/Conduit/StartupExtensions.cs | 5 +- .../Features/Articles/CreateTests.cs | 2 +- .../Features/Articles/DeleteTests.cs | 2 +- .../Features/Articles/EditTests.cs | 19 +++---- .../Features/Users/CreateTests.cs | 9 +--- .../Features/Users/UserHelpers.cs | 9 +--- .../StubCurrentUserAccessor.cs | 14 ++---- 53 files changed, 331 insertions(+), 723 deletions(-) diff --git a/build/Program.cs b/build/Program.cs index c4d4a6a9..3392c6d8 100644 --- a/build/Program.cs +++ b/build/Program.cs @@ -16,10 +16,7 @@ ForEach("publish", "**/bin", "**/obj"), dir => { - IEnumerable GetDirectories(string d) - { - return Glob.Directories(".", d); - } + IEnumerable GetDirectories(string d) => Glob.Directories(".", d); void RemoveDirectory(string d) { @@ -53,10 +50,7 @@ void RemoveDirectory(string d) DependsOn(Build), () => { - IEnumerable GetFiles(string d) - { - return Glob.Files(".", d); - } + IEnumerable GetFiles(string d) => Glob.Files(".", d); foreach (var file in GetFiles("tests/**/*.csproj")) { diff --git a/src/Conduit/Domain/Article.cs b/src/Conduit/Domain/Article.cs index 6edd920d..b5404e67 100644 --- a/src/Conduit/Domain/Article.cs +++ b/src/Conduit/Domain/Article.cs @@ -9,7 +9,7 @@ namespace Conduit.Domain; public class Article { [JsonIgnore] - public int ArticleId { get; set; } + public int ArticleId { get; init; } public string? Slug { get; set; } @@ -19,12 +19,12 @@ public class Article public string? Body { get; set; } - public Person? Author { get; set; } + public Person? Author { get; init; } - public List Comments { get; set; } = new(); + public List Comments { get; init; } = new(); [NotMapped] - public bool Favorited => ArticleFavorites?.Any() ?? false; + public bool Favorited => ArticleFavorites.Count != 0; [NotMapped] public int FavoritesCount => ArticleFavorites?.Count ?? 0; @@ -34,12 +34,12 @@ public class Article ArticleTags.Where(x => x.TagId is not null).Select(x => x.TagId!).ToList(); [JsonIgnore] - public List ArticleTags { get; set; } = new(); + public List ArticleTags { get; init; } = new(); [JsonIgnore] - public List ArticleFavorites { get; set; } = new(); + public List ArticleFavorites { get; init; } = new(); - public DateTime CreatedAt { get; set; } + public DateTime CreatedAt { get; init; } public DateTime UpdatedAt { get; set; } -} \ No newline at end of file +} diff --git a/src/Conduit/Domain/ArticleFavorite.cs b/src/Conduit/Domain/ArticleFavorite.cs index 56bd7b42..8531e616 100644 --- a/src/Conduit/Domain/ArticleFavorite.cs +++ b/src/Conduit/Domain/ArticleFavorite.cs @@ -2,9 +2,9 @@ namespace Conduit.Domain; public class ArticleFavorite { - public int ArticleId { get; set; } - public Article? Article { get; set; } + public int ArticleId { get; init; } + public Article? Article { get; init; } - public int PersonId { get; set; } - public Person? Person { get; set; } + public int PersonId { get; init; } + public Person? Person { get; init; } } \ No newline at end of file diff --git a/src/Conduit/Domain/ArticleTag.cs b/src/Conduit/Domain/ArticleTag.cs index ad8499cf..a3e31698 100644 --- a/src/Conduit/Domain/ArticleTag.cs +++ b/src/Conduit/Domain/ArticleTag.cs @@ -2,9 +2,9 @@ namespace Conduit.Domain; public class ArticleTag { - public int ArticleId { get; set; } - public Article? Article { get; set; } + public int ArticleId { get; init; } + public Article? Article { get; init; } - public string? TagId { get; set; } - public Tag? Tag { get; set; } + public string? TagId { get; init; } + public Tag? Tag { get; init; } } \ No newline at end of file diff --git a/src/Conduit/Domain/Comment.cs b/src/Conduit/Domain/Comment.cs index 5da37ba3..ea876a27 100644 --- a/src/Conduit/Domain/Comment.cs +++ b/src/Conduit/Domain/Comment.cs @@ -6,22 +6,22 @@ namespace Conduit.Domain; public class Comment { [JsonPropertyName("id")] - public int CommentId { get; set; } + public int CommentId { get; init; } - public string? Body { get; set; } + public string? Body { get; init; } - public Person? Author { get; set; } + public Person? Author { get; init; } [JsonIgnore] - public int AuthorId { get; set; } + public int AuthorId { get; init; } [JsonIgnore] - public Article? Article { get; set; } + public Article? Article { get; init; } [JsonIgnore] - public int ArticleId { get; set; } + public int ArticleId { get; init; } - public DateTime CreatedAt { get; set; } + public DateTime CreatedAt { get; init; } - public DateTime UpdatedAt { get; set; } + public DateTime UpdatedAt { get; init; } } \ No newline at end of file diff --git a/src/Conduit/Domain/FollowedPeople.cs b/src/Conduit/Domain/FollowedPeople.cs index 13c60f6e..8e3fcbe5 100644 --- a/src/Conduit/Domain/FollowedPeople.cs +++ b/src/Conduit/Domain/FollowedPeople.cs @@ -2,9 +2,9 @@ namespace Conduit.Domain; public class FollowedPeople { - public int ObserverId { get; set; } - public Person? Observer { get; set; } + public int ObserverId { get; init; } + public Person? Observer { get; init; } - public int TargetId { get; set; } - public Person? Target { get; set; } + public int TargetId { get; init; } + public Person? Target { get; init; } } \ No newline at end of file diff --git a/src/Conduit/Domain/Person.cs b/src/Conduit/Domain/Person.cs index 9a5cb376..7e9a468b 100644 --- a/src/Conduit/Domain/Person.cs +++ b/src/Conduit/Domain/Person.cs @@ -7,7 +7,7 @@ namespace Conduit.Domain; public class Person { [JsonIgnore] - public int PersonId { get; set; } + public int PersonId { get; init; } public string? Username { get; set; } @@ -18,17 +18,17 @@ public class Person public string? Image { get; set; } [JsonIgnore] - public List ArticleFavorites { get; set; } = new(); + public List ArticleFavorites { get; init; } = new(); [JsonIgnore] - public List Following { get; set; } = new(); + public List Following { get; init; } = new(); [JsonIgnore] - public List Followers { get; set; } = new(); + public List Followers { get; init; } = new(); [JsonIgnore] - public byte[] Hash { get; set; } = Array.Empty(); + public byte[] Hash { get; set; } = []; [JsonIgnore] - public byte[] Salt { get; set; } = Array.Empty(); -} \ No newline at end of file + public byte[] Salt { get; set; } = []; +} diff --git a/src/Conduit/Domain/Tag.cs b/src/Conduit/Domain/Tag.cs index 753b8a2f..4100e34e 100644 --- a/src/Conduit/Domain/Tag.cs +++ b/src/Conduit/Domain/Tag.cs @@ -4,7 +4,7 @@ namespace Conduit.Domain; public class Tag { - public string? TagId { get; set; } + public string? TagId { get; init; } - public List ArticleTags { get; set; } = new(); + public List ArticleTags { get; init; } = new(); } \ No newline at end of file diff --git a/src/Conduit/Features/Articles/ArticlesController.cs b/src/Conduit/Features/Articles/ArticlesController.cs index 9aeda171..964370cd 100644 --- a/src/Conduit/Features/Articles/ArticlesController.cs +++ b/src/Conduit/Features/Articles/ArticlesController.cs @@ -8,15 +8,8 @@ namespace Conduit.Features.Articles; [Route("articles")] -public class ArticlesController : Controller +public class ArticlesController(IMediator mediator) : Controller { - private readonly IMediator _mediator; - - public ArticlesController(IMediator mediator) - { - _mediator = mediator; - } - [HttpGet] public Task Get( [FromQuery] string tag, @@ -25,13 +18,11 @@ public Task Get( [FromQuery] int? limit, [FromQuery] int? offset, CancellationToken cancellationToken - ) - { - return _mediator.Send( + ) => + mediator.Send( new List.Query(tag, author, favorited, limit, offset), cancellationToken ); - } [HttpGet("feed")] public Task GetFeed( @@ -41,28 +32,20 @@ public Task GetFeed( [FromQuery] int? limit, [FromQuery] int? offset, CancellationToken cancellationToken - ) - { - return _mediator.Send( - new List.Query(tag, author, favorited, limit, offset) { IsFeed = true } - ); - } + ) => + mediator.Send( + new List.Query(tag, author, favorited, limit, offset) { IsFeed = true }, cancellationToken); [HttpGet("{slug}")] - public Task Get(string slug, CancellationToken cancellationToken) - { - return _mediator.Send(new Details.Query(slug), cancellationToken); - } + public Task Get(string slug, CancellationToken cancellationToken) => mediator.Send(new Details.Query(slug), cancellationToken); [HttpPost] [Authorize(AuthenticationSchemes = JwtIssuerOptions.Schemes)] public Task Create( [FromBody] Create.Command command, CancellationToken cancellationToken - ) - { - return _mediator.Send(command, cancellationToken); - } + ) => + mediator.Send(command, cancellationToken); [HttpPut("{slug}")] [Authorize(AuthenticationSchemes = JwtIssuerOptions.Schemes)] @@ -70,15 +53,10 @@ public Task Edit( string slug, [FromBody] Edit.Model model, CancellationToken cancellationToken - ) - { - return _mediator.Send(new Edit.Command(model, slug), cancellationToken); - } + ) => + mediator.Send(new Edit.Command(model, slug), cancellationToken); [HttpDelete("{slug}")] [Authorize(AuthenticationSchemes = JwtIssuerOptions.Schemes)] - public Task Delete(string slug, CancellationToken cancellationToken) - { - return _mediator.Send(new Delete.Command(slug), cancellationToken); - } -} \ No newline at end of file + public Task Delete(string slug, CancellationToken cancellationToken) => mediator.Send(new Delete.Command(slug), cancellationToken); +} diff --git a/src/Conduit/Features/Articles/Create.cs b/src/Conduit/Features/Articles/Create.cs index 3a7a55f8..815e4b68 100644 --- a/src/Conduit/Features/Articles/Create.cs +++ b/src/Conduit/Features/Articles/Create.cs @@ -15,13 +15,13 @@ public class Create { public class ArticleData { - public string? Title { get; set; } + public string? Title { get; init; } - public string? Description { get; set; } + public string? Description { get; init; } - public string? Body { get; set; } + public string? Body { get; init; } - public string[]? TagList { get; set; } + public string[]? TagList { get; init; } } public class ArticleDataValidator : AbstractValidator @@ -38,42 +38,31 @@ public record Command(ArticleData Article) : IRequest; public class CommandValidator : AbstractValidator { - public CommandValidator() - { - RuleFor(x => x.Article).NotNull().SetValidator(new ArticleDataValidator()); - } + public CommandValidator() => RuleFor(x => x.Article).NotNull().SetValidator(new ArticleDataValidator()); } - public class Handler : IRequestHandler + public class Handler(ConduitContext context, ICurrentUserAccessor currentUserAccessor) + : IRequestHandler { - private readonly ConduitContext _context; - private readonly ICurrentUserAccessor _currentUserAccessor; - - public Handler(ConduitContext context, ICurrentUserAccessor currentUserAccessor) - { - _context = context; - _currentUserAccessor = currentUserAccessor; - } - public async Task Handle( Command message, CancellationToken cancellationToken ) { - var author = await _context.Persons.FirstAsync( - x => x.Username == _currentUserAccessor.GetCurrentUsername(), + var author = await context.Persons.FirstAsync( + x => x.Username == currentUserAccessor.GetCurrentUsername(), cancellationToken ); var tags = new List(); foreach (var tag in (message.Article.TagList ?? Enumerable.Empty())) { - var t = await _context.Tags.FindAsync(tag); + var t = await context.Tags.FindAsync(tag); if (t == null) { t = new Tag() { TagId = tag }; - await _context.Tags.AddAsync(t, cancellationToken); + await context.Tags.AddAsync(t, cancellationToken); //save immediately for reuse - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); } tags.Add(t); } @@ -88,16 +77,16 @@ CancellationToken cancellationToken Title = message.Article.Title, Slug = message.Article.Title.GenerateSlug() }; - await _context.Articles.AddAsync(article, cancellationToken); + await context.Articles.AddAsync(article, cancellationToken); - await _context.ArticleTags.AddRangeAsync( + await context.ArticleTags.AddRangeAsync( tags.Select(x => new ArticleTag() { Article = article, Tag = x }), cancellationToken ); - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); return new ArticleEnvelope(article); } } -} \ No newline at end of file +} diff --git a/src/Conduit/Features/Articles/Delete.cs b/src/Conduit/Features/Articles/Delete.cs index 4779caad..09366dc7 100644 --- a/src/Conduit/Features/Articles/Delete.cs +++ b/src/Conduit/Features/Articles/Delete.cs @@ -18,16 +18,12 @@ public class CommandValidator : AbstractValidator public CommandValidator() => RuleFor(x => x.Slug).NotNull().NotEmpty(); } - public class QueryHandler : IRequestHandler + public class QueryHandler(ConduitContext context) : IRequestHandler { - private readonly ConduitContext _context; - - public QueryHandler(ConduitContext context) => _context = context; - public async Task Handle(Command message, CancellationToken cancellationToken) { var article = - await _context.Articles.FirstOrDefaultAsync( + await context.Articles.FirstOrDefaultAsync( x => x.Slug == message.Slug, cancellationToken ) @@ -36,9 +32,9 @@ await _context.Articles.FirstOrDefaultAsync( new { Article = Constants.NOT_FOUND } ); - _context.Articles.Remove(article); - await _context.SaveChangesAsync(cancellationToken); + context.Articles.Remove(article); + await context.SaveChangesAsync(cancellationToken); await Task.FromResult(Unit.Value); } } -} \ No newline at end of file +} diff --git a/src/Conduit/Features/Articles/Details.cs b/src/Conduit/Features/Articles/Details.cs index a6fee96f..86655c0e 100644 --- a/src/Conduit/Features/Articles/Details.cs +++ b/src/Conduit/Features/Articles/Details.cs @@ -18,18 +18,14 @@ public class QueryValidator : AbstractValidator public QueryValidator() => RuleFor(x => x.Slug).NotNull().NotEmpty(); } - public class QueryHandler : IRequestHandler + public class QueryHandler(ConduitContext context) : IRequestHandler { - private readonly ConduitContext _context; - - public QueryHandler(ConduitContext context) => _context = context; - public async Task Handle( Query message, CancellationToken cancellationToken ) { - var article = await _context.Articles + var article = await context.Articles .GetAllData() .FirstOrDefaultAsync(x => x.Slug == message.Slug, cancellationToken); @@ -43,4 +39,4 @@ CancellationToken cancellationToken return new ArticleEnvelope(article); } } -} \ No newline at end of file +} diff --git a/src/Conduit/Features/Articles/Edit.cs b/src/Conduit/Features/Articles/Edit.cs index f6cfca32..9b54eb25 100644 --- a/src/Conduit/Features/Articles/Edit.cs +++ b/src/Conduit/Features/Articles/Edit.cs @@ -15,16 +15,7 @@ namespace Conduit.Features.Articles; public class Edit { - public class ArticleData - { - public string? Title { get; set; } - - public string? Description { get; set; } - - public string? Body { get; set; } - - public string[]? TagList { get; set; } - } + public record ArticleData(string? Title, string? Description, string? Body, string[]? TagList); public record Command(Model Model, string Slug) : IRequest; @@ -32,27 +23,17 @@ public record Model(ArticleData Article); public class CommandValidator : AbstractValidator { - public CommandValidator() - { - RuleFor(x => x.Model.Article).NotNull(); - } + public CommandValidator() => RuleFor(x => x.Model.Article).NotNull(); } - public class Handler : IRequestHandler + public class Handler(ConduitContext context) : IRequestHandler { - private readonly ConduitContext _context; - - public Handler(ConduitContext context) - { - _context = context; - } - public async Task Handle( Command message, CancellationToken cancellationToken ) { - var article = await _context.Articles + var article = await context.Articles .Include(x => x.ArticleTags) // include also the article tags since they also need to be updated .Where(x => x.Slug == message.Slug) .FirstOrDefaultAsync(cancellationToken); @@ -77,30 +58,30 @@ CancellationToken cancellationToken var articleTagsToDelete = GetArticleTagsToDelete(article, articleTagList); if ( - _context.ChangeTracker.Entries().First(x => x.Entity == article).State + context.ChangeTracker.Entries().First(x => x.Entity == article).State == EntityState.Modified - || articleTagsToCreate.Any() - || articleTagsToDelete.Any() + || articleTagsToCreate.Count != 0 + || articleTagsToDelete.Count != 0 ) { article.UpdatedAt = DateTime.UtcNow; } // ensure context is tracking any tags that are about to be created so that it won't attempt to insert a duplicate - _context.Tags.AttachRange( + context.Tags.AttachRange( articleTagsToCreate.Where(x => x.Tag is not null).Select(a => a.Tag!).ToArray() ); // add the new article tags - await _context.ArticleTags.AddRangeAsync(articleTagsToCreate, cancellationToken); + await context.ArticleTags.AddRangeAsync(articleTagsToCreate, cancellationToken); // delete the tags that do not exist anymore - _context.ArticleTags.RemoveRange(articleTagsToDelete); + context.ArticleTags.RemoveRange(articleTagsToDelete); - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); article = - await _context.Articles + await context.Articles .GetAllData() .Where(x => x.Slug == article.Slug) .FirstOrDefaultAsync( diff --git a/src/Conduit/Features/Articles/List.cs b/src/Conduit/Features/Articles/List.cs index 7ef61ded..71937cd1 100644 --- a/src/Conduit/Features/Articles/List.cs +++ b/src/Conduit/Features/Articles/List.cs @@ -21,30 +21,22 @@ public record Query( bool IsFeed = false ) : IRequest; - public class QueryHandler : IRequestHandler + public class QueryHandler(ConduitContext context, ICurrentUserAccessor currentUserAccessor) + : IRequestHandler { - private readonly ConduitContext _context; - private readonly ICurrentUserAccessor _currentUserAccessor; - - public QueryHandler(ConduitContext context, ICurrentUserAccessor currentUserAccessor) - { - _context = context; - _currentUserAccessor = currentUserAccessor; - } - public async Task Handle( Query message, CancellationToken cancellationToken ) { - var queryable = _context.Articles.GetAllData(); + var queryable = context.Articles.GetAllData(); - if (message.IsFeed && _currentUserAccessor.GetCurrentUsername() != null) + if (message.IsFeed && currentUserAccessor.GetCurrentUsername() != null) { - var currentUser = await _context.Persons + var currentUser = await context.Persons .Include(x => x.Following) .FirstOrDefaultAsync( - x => x.Username == _currentUserAccessor.GetCurrentUsername(), + x => x.Username == currentUserAccessor.GetCurrentUsername(), cancellationToken ); @@ -65,7 +57,7 @@ CancellationToken cancellationToken if (!string.IsNullOrWhiteSpace(message.Tag)) { - var tag = await _context.ArticleTags.FirstOrDefaultAsync( + var tag = await context.ArticleTags.FirstOrDefaultAsync( x => x.TagId == message.Tag, cancellationToken ); @@ -83,7 +75,7 @@ CancellationToken cancellationToken if (!string.IsNullOrWhiteSpace(message.Author)) { - var author = await _context.Persons.FirstOrDefaultAsync( + var author = await context.Persons.FirstOrDefaultAsync( x => x.Username == message.Author, cancellationToken ); @@ -99,7 +91,7 @@ CancellationToken cancellationToken if (!string.IsNullOrWhiteSpace(message.FavoritedUsername)) { - var author = await _context.Persons.FirstOrDefaultAsync( + var author = await context.Persons.FirstOrDefaultAsync( x => x.Username == message.FavoritedUsername, cancellationToken ); diff --git a/src/Conduit/Features/Comments/CommentsController.cs b/src/Conduit/Features/Comments/CommentsController.cs index 920615f4..4ff3ad67 100644 --- a/src/Conduit/Features/Comments/CommentsController.cs +++ b/src/Conduit/Features/Comments/CommentsController.cs @@ -8,36 +8,21 @@ namespace Conduit.Features.Comments; [Route("articles")] -public class CommentsController : Controller +public class CommentsController(IMediator mediator) : Controller { - private readonly IMediator _mediator; - - public CommentsController(IMediator mediator) - { - _mediator = mediator; - } - [HttpPost("{slug}/comments")] [Authorize(AuthenticationSchemes = JwtIssuerOptions.Schemes)] public Task Create( string slug, [FromBody] Create.Model model, CancellationToken cancellationToken - ) - { - return _mediator.Send(new Create.Command(model, slug), cancellationToken); - } + ) => + mediator.Send(new Create.Command(model, slug), cancellationToken); [HttpGet("{slug}/comments")] - public Task Get(string slug, CancellationToken cancellationToken) - { - return _mediator.Send(new List.Query(slug), cancellationToken); - } + public Task Get(string slug, CancellationToken cancellationToken) => mediator.Send(new List.Query(slug), cancellationToken); [HttpDelete("{slug}/comments/{id}")] [Authorize(AuthenticationSchemes = JwtIssuerOptions.Schemes)] - public Task Delete(string slug, int id, CancellationToken cancellationToken) - { - return _mediator.Send(new Delete.Command(slug, id), cancellationToken); - } -} \ No newline at end of file + public Task Delete(string slug, int id, CancellationToken cancellationToken) => mediator.Send(new Delete.Command(slug, id), cancellationToken); +} diff --git a/src/Conduit/Features/Comments/Create.cs b/src/Conduit/Features/Comments/Create.cs index f1c3d369..9c0a742c 100644 --- a/src/Conduit/Features/Comments/Create.cs +++ b/src/Conduit/Features/Comments/Create.cs @@ -21,29 +21,18 @@ public record Model(CommentData Comment) : IRequest; public class CommandValidator : AbstractValidator { - public CommandValidator() - { - RuleFor(x => x.Model.Comment.Body).NotEmpty(); - } + public CommandValidator() => RuleFor(x => x.Model.Comment.Body).NotEmpty(); } - public class Handler : IRequestHandler + public class Handler(ConduitContext context, ICurrentUserAccessor currentUserAccessor) + : IRequestHandler { - private readonly ConduitContext _context; - private readonly ICurrentUserAccessor _currentUserAccessor; - - public Handler(ConduitContext context, ICurrentUserAccessor currentUserAccessor) - { - _context = context; - _currentUserAccessor = currentUserAccessor; - } - public async Task Handle( Command message, CancellationToken cancellationToken ) { - var article = await _context.Articles + var article = await context.Articles .Include(x => x.Comments) .FirstOrDefaultAsync(x => x.Slug == message.Slug, cancellationToken); @@ -55,8 +44,8 @@ CancellationToken cancellationToken ); } - var author = await _context.Persons.FirstAsync( - x => x.Username == _currentUserAccessor.GetCurrentUsername(), + var author = await context.Persons.FirstAsync( + x => x.Username == currentUserAccessor.GetCurrentUsername(), cancellationToken ); @@ -67,13 +56,13 @@ CancellationToken cancellationToken CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow }; - await _context.Comments.AddAsync(comment, cancellationToken); + await context.Comments.AddAsync(comment, cancellationToken); article.Comments.Add(comment); - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); return new CommentEnvelope(comment); } } -} \ No newline at end of file +} diff --git a/src/Conduit/Features/Comments/Delete.cs b/src/Conduit/Features/Comments/Delete.cs index 5c59154b..9806f0bb 100644 --- a/src/Conduit/Features/Comments/Delete.cs +++ b/src/Conduit/Features/Comments/Delete.cs @@ -19,16 +19,12 @@ public class CommandValidator : AbstractValidator public CommandValidator() => RuleFor(x => x.Slug).NotNull().NotEmpty(); } - public class QueryHandler : IRequestHandler + public class QueryHandler(ConduitContext context) : IRequestHandler { - private readonly ConduitContext _context; - - public QueryHandler(ConduitContext context) => _context = context; - public async Task Handle(Command message, CancellationToken cancellationToken) { var article = - await _context.Articles + await context.Articles .Include(x => x.Comments) .FirstOrDefaultAsync(x => x.Slug == message.Slug, cancellationToken) ?? throw new RestException( @@ -43,9 +39,9 @@ await _context.Articles new { Comment = Constants.NOT_FOUND } ); - _context.Comments.Remove(comment); - await _context.SaveChangesAsync(cancellationToken); + context.Comments.Remove(comment); + await context.SaveChangesAsync(cancellationToken); await Task.FromResult(Unit.Value); } } -} \ No newline at end of file +} diff --git a/src/Conduit/Features/Comments/List.cs b/src/Conduit/Features/Comments/List.cs index 8b02e972..c8e4bf31 100644 --- a/src/Conduit/Features/Comments/List.cs +++ b/src/Conduit/Features/Comments/List.cs @@ -12,21 +12,14 @@ public class List { public record Query(string Slug) : IRequest; - public class QueryHandler : IRequestHandler + public class QueryHandler(ConduitContext context) : IRequestHandler { - private readonly ConduitContext _context; - - public QueryHandler(ConduitContext context) - { - _context = context; - } - public async Task Handle( Query message, CancellationToken cancellationToken ) { - var article = await _context.Articles + var article = await context.Articles .Include(x => x.Comments) .ThenInclude(x => x.Author) .FirstOrDefaultAsync(x => x.Slug == message.Slug, cancellationToken); @@ -42,4 +35,4 @@ CancellationToken cancellationToken return new CommentsEnvelope(article.Comments); } } -} \ No newline at end of file +} diff --git a/src/Conduit/Features/Favorites/Add.cs b/src/Conduit/Features/Favorites/Add.cs index 95d08745..9f5a0ce0 100644 --- a/src/Conduit/Features/Favorites/Add.cs +++ b/src/Conduit/Features/Favorites/Add.cs @@ -17,29 +17,18 @@ public record Command(string Slug) : IRequest; public class CommandValidator : AbstractValidator { - public CommandValidator() - { - DefaultValidatorExtensions.NotNull(RuleFor(x => x.Slug)).NotEmpty(); - } + public CommandValidator() => RuleFor(x => x.Slug).NotNull().NotEmpty(); } - public class QueryHandler : IRequestHandler + public class QueryHandler(ConduitContext context, ICurrentUserAccessor currentUserAccessor) + : IRequestHandler { - private readonly ConduitContext _context; - private readonly ICurrentUserAccessor _currentUserAccessor; - - public QueryHandler(ConduitContext context, ICurrentUserAccessor currentUserAccessor) - { - _context = context; - _currentUserAccessor = currentUserAccessor; - } - public async Task Handle( Command message, CancellationToken cancellationToken ) { - var article = await _context.Articles.FirstOrDefaultAsync( + var article = await context.Articles.FirstOrDefaultAsync( x => x.Slug == message.Slug, cancellationToken ); @@ -52,8 +41,8 @@ CancellationToken cancellationToken ); } - var person = await _context.Persons.FirstOrDefaultAsync( - x => x.Username == _currentUserAccessor.GetCurrentUsername(), + var person = await context.Persons.FirstOrDefaultAsync( + x => x.Username == currentUserAccessor.GetCurrentUsername(), cancellationToken ); @@ -65,7 +54,7 @@ CancellationToken cancellationToken ); } - var favorite = await _context.ArticleFavorites.FirstOrDefaultAsync( + var favorite = await context.ArticleFavorites.FirstOrDefaultAsync( x => x.ArticleId == article.ArticleId && x.PersonId == person.PersonId, cancellationToken ); @@ -79,14 +68,14 @@ CancellationToken cancellationToken Person = person, PersonId = person.PersonId }; - await _context.ArticleFavorites.AddAsync(favorite, cancellationToken); - await _context.SaveChangesAsync(cancellationToken); + await context.ArticleFavorites.AddAsync(favorite, cancellationToken); + await context.SaveChangesAsync(cancellationToken); } article = - await _context.Articles + await context.Articles .GetAllData() .FirstOrDefaultAsync( x => x.ArticleId == article.ArticleId, diff --git a/src/Conduit/Features/Favorites/Delete.cs b/src/Conduit/Features/Favorites/Delete.cs index 9839b4bd..84d5f06f 100644 --- a/src/Conduit/Features/Favorites/Delete.cs +++ b/src/Conduit/Features/Favorites/Delete.cs @@ -16,30 +16,19 @@ public record Command(string Slug) : IRequest; public class CommandValidator : AbstractValidator { - public CommandValidator() - { - DefaultValidatorExtensions.NotNull(RuleFor(x => x.Slug)).NotEmpty(); - } + public CommandValidator() => RuleFor(x => x.Slug).NotNull().NotEmpty(); } - public class QueryHandler : IRequestHandler + public class QueryHandler(ConduitContext context, ICurrentUserAccessor currentUserAccessor) + : IRequestHandler { - private readonly ConduitContext _context; - private readonly ICurrentUserAccessor _currentUserAccessor; - - public QueryHandler(ConduitContext context, ICurrentUserAccessor currentUserAccessor) - { - _context = context; - _currentUserAccessor = currentUserAccessor; - } - public async Task Handle( Command message, CancellationToken cancellationToken ) { var article = - await _context.Articles.FirstOrDefaultAsync( + await context.Articles.FirstOrDefaultAsync( x => x.Slug == message.Slug, cancellationToken ) @@ -48,8 +37,8 @@ await _context.Articles.FirstOrDefaultAsync( new { Article = Constants.NOT_FOUND } ); - var person = await _context.Persons.FirstOrDefaultAsync( - x => x.Username == _currentUserAccessor.GetCurrentUsername(), + var person = await context.Persons.FirstOrDefaultAsync( + x => x.Username == currentUserAccessor.GetCurrentUsername(), cancellationToken ); if (person is null) @@ -60,19 +49,19 @@ await _context.Articles.FirstOrDefaultAsync( ); } - var favorite = await _context.ArticleFavorites.FirstOrDefaultAsync( + var favorite = await context.ArticleFavorites.FirstOrDefaultAsync( x => x.ArticleId == article.ArticleId && x.PersonId == person.PersonId, cancellationToken ); if (favorite != null) { - _context.ArticleFavorites.Remove(favorite); - await _context.SaveChangesAsync(cancellationToken); + context.ArticleFavorites.Remove(favorite); + await context.SaveChangesAsync(cancellationToken); } article = - await _context.Articles + await context.Articles .GetAllData() .FirstOrDefaultAsync( x => x.ArticleId == article.ArticleId, diff --git a/src/Conduit/Features/Favorites/FavoritesController.cs b/src/Conduit/Features/Favorites/FavoritesController.cs index 3a70b054..ba2c677a 100644 --- a/src/Conduit/Features/Favorites/FavoritesController.cs +++ b/src/Conduit/Features/Favorites/FavoritesController.cs @@ -9,29 +9,17 @@ namespace Conduit.Features.Favorites; [Route("articles")] -public class FavoritesController : Controller +public class FavoritesController(IMediator mediator) : Controller { - private readonly IMediator _mediator; - - public FavoritesController(IMediator mediator) - { - _mediator = mediator; - } - [HttpPost("{slug}/favorite")] [Authorize(AuthenticationSchemes = JwtIssuerOptions.Schemes)] - public Task FavoriteAdd(string slug, CancellationToken cancellationToken) - { - return _mediator.Send(new Add.Command(slug), cancellationToken); - } + public Task FavoriteAdd(string slug, CancellationToken cancellationToken) => mediator.Send(new Add.Command(slug), cancellationToken); [HttpDelete("{slug}/favorite")] [Authorize(AuthenticationSchemes = JwtIssuerOptions.Schemes)] public Task FavoriteDelete( string slug, CancellationToken cancellationToken - ) - { - return _mediator.Send(new Delete.Command(slug), cancellationToken); - } -} \ No newline at end of file + ) => + mediator.Send(new Delete.Command(slug), cancellationToken); +} diff --git a/src/Conduit/Features/Followers/Add.cs b/src/Conduit/Features/Followers/Add.cs index 0d07bd59..234b851e 100644 --- a/src/Conduit/Features/Followers/Add.cs +++ b/src/Conduit/Features/Followers/Add.cs @@ -17,35 +17,21 @@ public record Command(string Username) : IRequest; public class CommandValidator : AbstractValidator { - public CommandValidator() - { - DefaultValidatorExtensions.NotNull(RuleFor(x => x.Username)).NotEmpty(); - } + public CommandValidator() => RuleFor(x => x.Username).NotNull().NotEmpty(); } - public class QueryHandler : IRequestHandler + public class QueryHandler( + ConduitContext context, + ICurrentUserAccessor currentUserAccessor, + IProfileReader profileReader) + : IRequestHandler { - private readonly ConduitContext _context; - private readonly ICurrentUserAccessor _currentUserAccessor; - private readonly IProfileReader _profileReader; - - public QueryHandler( - ConduitContext context, - ICurrentUserAccessor currentUserAccessor, - IProfileReader profileReader - ) - { - _context = context; - _currentUserAccessor = currentUserAccessor; - _profileReader = profileReader; - } - public async Task Handle( Command message, CancellationToken cancellationToken ) { - var target = await _context.Persons.FirstOrDefaultAsync( + var target = await context.Persons.FirstOrDefaultAsync( x => x.Username == message.Username, cancellationToken ); @@ -58,8 +44,8 @@ CancellationToken cancellationToken ); } - var observer = await _context.Persons.FirstOrDefaultAsync( - x => x.Username == _currentUserAccessor.GetCurrentUsername(), + var observer = await context.Persons.FirstOrDefaultAsync( + x => x.Username == currentUserAccessor.GetCurrentUsername(), cancellationToken ); @@ -71,7 +57,7 @@ CancellationToken cancellationToken ); } - var followedPeople = await _context.FollowedPeople.FirstOrDefaultAsync( + var followedPeople = await context.FollowedPeople.FirstOrDefaultAsync( x => x.ObserverId == observer.PersonId && x.TargetId == target.PersonId, cancellationToken ); @@ -85,11 +71,11 @@ CancellationToken cancellationToken Target = target, TargetId = target.PersonId }; - await _context.FollowedPeople.AddAsync(followedPeople, cancellationToken); - await _context.SaveChangesAsync(cancellationToken); + await context.FollowedPeople.AddAsync(followedPeople, cancellationToken); + await context.SaveChangesAsync(cancellationToken); } - return await _profileReader.ReadProfile(message.Username, cancellationToken); + return await profileReader.ReadProfile(message.Username, cancellationToken); } } } diff --git a/src/Conduit/Features/Followers/Delete.cs b/src/Conduit/Features/Followers/Delete.cs index 7ef62e5c..2d7a719a 100644 --- a/src/Conduit/Features/Followers/Delete.cs +++ b/src/Conduit/Features/Followers/Delete.cs @@ -16,35 +16,21 @@ public record Command(string Username) : IRequest; public class CommandValidator : AbstractValidator { - public CommandValidator() - { - DefaultValidatorExtensions.NotNull(RuleFor(x => x.Username)).NotEmpty(); - } + public CommandValidator() => RuleFor(x => x.Username).NotNull().NotEmpty(); } - public class QueryHandler : IRequestHandler + public class QueryHandler( + ConduitContext context, + ICurrentUserAccessor currentUserAccessor, + IProfileReader profileReader) + : IRequestHandler { - private readonly ConduitContext _context; - private readonly ICurrentUserAccessor _currentUserAccessor; - private readonly IProfileReader _profileReader; - - public QueryHandler( - ConduitContext context, - ICurrentUserAccessor currentUserAccessor, - IProfileReader profileReader - ) - { - _context = context; - _currentUserAccessor = currentUserAccessor; - _profileReader = profileReader; - } - public async Task Handle( Command message, CancellationToken cancellationToken ) { - var target = await _context.Persons.FirstOrDefaultAsync( + var target = await context.Persons.FirstOrDefaultAsync( x => x.Username == message.Username, cancellationToken ); @@ -57,8 +43,8 @@ CancellationToken cancellationToken ); } - var observer = await _context.Persons.FirstOrDefaultAsync( - x => x.Username == _currentUserAccessor.GetCurrentUsername(), + var observer = await context.Persons.FirstOrDefaultAsync( + x => x.Username == currentUserAccessor.GetCurrentUsername(), cancellationToken ); @@ -70,18 +56,18 @@ CancellationToken cancellationToken ); } - var followedPeople = await _context.FollowedPeople.FirstOrDefaultAsync( + var followedPeople = await context.FollowedPeople.FirstOrDefaultAsync( x => x.ObserverId == observer.PersonId && x.TargetId == target.PersonId, cancellationToken ); if (followedPeople != null) { - _context.FollowedPeople.Remove(followedPeople); - await _context.SaveChangesAsync(cancellationToken); + context.FollowedPeople.Remove(followedPeople); + await context.SaveChangesAsync(cancellationToken); } - return await _profileReader.ReadProfile(message.Username, cancellationToken); + return await profileReader.ReadProfile(message.Username, cancellationToken); } } } diff --git a/src/Conduit/Features/Followers/FollowersController.cs b/src/Conduit/Features/Followers/FollowersController.cs index e011de98..8e8bd47e 100644 --- a/src/Conduit/Features/Followers/FollowersController.cs +++ b/src/Conduit/Features/Followers/FollowersController.cs @@ -9,26 +9,13 @@ namespace Conduit.Features.Followers; [Route("profiles")] -public class FollowersController : Controller +public class FollowersController(IMediator mediator) : Controller { - private readonly IMediator _mediator; - - public FollowersController(IMediator mediator) - { - _mediator = mediator; - } - [HttpPost("{username}/follow")] [Authorize(AuthenticationSchemes = JwtIssuerOptions.Schemes)] - public Task Follow(string username, CancellationToken cancellationToken) - { - return _mediator.Send(new Add.Command(username), cancellationToken); - } + public Task Follow(string username, CancellationToken cancellationToken) => mediator.Send(new Add.Command(username), cancellationToken); [HttpDelete("{username}/follow")] [Authorize(AuthenticationSchemes = JwtIssuerOptions.Schemes)] - public Task Unfollow(string username, CancellationToken cancellationToken) - { - return _mediator.Send(new Delete.Command(username), cancellationToken); - } -} \ No newline at end of file + public Task Unfollow(string username, CancellationToken cancellationToken) => mediator.Send(new Delete.Command(username), cancellationToken); +} diff --git a/src/Conduit/Features/Profiles/Details.cs b/src/Conduit/Features/Profiles/Details.cs index 511ddfe4..fc759ef3 100644 --- a/src/Conduit/Features/Profiles/Details.cs +++ b/src/Conduit/Features/Profiles/Details.cs @@ -11,24 +11,11 @@ public record Query(string Username) : IRequest; public class QueryValidator : AbstractValidator { - public QueryValidator() - { - RuleFor(x => x.Username).NotEmpty(); - } + public QueryValidator() => RuleFor(x => x.Username).NotEmpty(); } - public class QueryHandler : IRequestHandler + public class QueryHandler(IProfileReader profileReader) : IRequestHandler { - private readonly IProfileReader _profileReader; - - public QueryHandler(IProfileReader profileReader) - { - _profileReader = profileReader; - } - - public Task Handle(Query message, CancellationToken cancellationToken) - { - return _profileReader.ReadProfile(message.Username, cancellationToken); - } + public Task Handle(Query message, CancellationToken cancellationToken) => profileReader.ReadProfile(message.Username, cancellationToken); } -} \ No newline at end of file +} diff --git a/src/Conduit/Features/Profiles/MappingProfile.cs b/src/Conduit/Features/Profiles/MappingProfile.cs index 7733f03f..24c9627d 100644 --- a/src/Conduit/Features/Profiles/MappingProfile.cs +++ b/src/Conduit/Features/Profiles/MappingProfile.cs @@ -4,8 +4,5 @@ namespace Conduit.Features.Profiles; public class MappingProfile : AutoMapper.Profile { - public MappingProfile() - { - CreateMap(MemberList.None); - } + public MappingProfile() => CreateMap(MemberList.None); } \ No newline at end of file diff --git a/src/Conduit/Features/Profiles/Profile.cs b/src/Conduit/Features/Profiles/Profile.cs index c76eacc9..c42f9137 100644 --- a/src/Conduit/Features/Profiles/Profile.cs +++ b/src/Conduit/Features/Profiles/Profile.cs @@ -4,11 +4,11 @@ namespace Conduit.Features.Profiles; public class Profile { - public string? Username { get; set; } + public string? Username { get; init; } - public string? Bio { get; set; } + public string? Bio { get; init; } - public string? Image { get; set; } + public string? Image { get; init; } [JsonPropertyName("following")] public bool IsFollowed { get; set; } diff --git a/src/Conduit/Features/Profiles/ProfileReader.cs b/src/Conduit/Features/Profiles/ProfileReader.cs index 613d542b..eb1d80ae 100644 --- a/src/Conduit/Features/Profiles/ProfileReader.cs +++ b/src/Conduit/Features/Profiles/ProfileReader.cs @@ -9,31 +9,20 @@ namespace Conduit.Features.Profiles; -public class ProfileReader : IProfileReader +public class ProfileReader( + ConduitContext context, + ICurrentUserAccessor currentUserAccessor, + IMapper mapper) + : IProfileReader { - private readonly ConduitContext _context; - private readonly ICurrentUserAccessor _currentUserAccessor; - private readonly IMapper _mapper; - - public ProfileReader( - ConduitContext context, - ICurrentUserAccessor currentUserAccessor, - IMapper mapper - ) - { - _context = context; - _currentUserAccessor = currentUserAccessor; - _mapper = mapper; - } - public async Task ReadProfile( string username, CancellationToken cancellationToken ) { - var currentUserName = _currentUserAccessor.GetCurrentUsername(); + var currentUserName = currentUserAccessor.GetCurrentUsername(); - var person = await _context.Persons + var person = await context.Persons .AsNoTracking() .FirstOrDefaultAsync(x => x.Username == username, cancellationToken); if (person is null) @@ -51,11 +40,11 @@ CancellationToken cancellationToken new { User = Constants.NOT_FOUND } ); } - var profile = _mapper.Map(person); + var profile = mapper.Map(person); if (currentUserName != null) { - var currentPerson = await _context.Persons + var currentPerson = await context.Persons .Include(x => x.Following) .Include(x => x.Followers) .FirstOrDefaultAsync(x => x.Username == currentUserName, cancellationToken); diff --git a/src/Conduit/Features/Profiles/ProfilesController.cs b/src/Conduit/Features/Profiles/ProfilesController.cs index 4dc16597..15a5d33e 100644 --- a/src/Conduit/Features/Profiles/ProfilesController.cs +++ b/src/Conduit/Features/Profiles/ProfilesController.cs @@ -6,18 +6,8 @@ namespace Conduit.Features.Profiles; [Route("profiles")] -public class ProfilesController : Controller +public class ProfilesController(IMediator mediator) : Controller { - private readonly IMediator _mediator; - - public ProfilesController(IMediator mediator) - { - _mediator = mediator; - } - [HttpGet("{username}")] - public Task Get(string username, CancellationToken cancellationToken) - { - return _mediator.Send(new Details.Query(username), cancellationToken); - } -} \ No newline at end of file + public Task Get(string username, CancellationToken cancellationToken) => mediator.Send(new Details.Query(username), cancellationToken); +} diff --git a/src/Conduit/Features/Tags/List.cs b/src/Conduit/Features/Tags/List.cs index c10eb79e..06e78a65 100644 --- a/src/Conduit/Features/Tags/List.cs +++ b/src/Conduit/Features/Tags/List.cs @@ -12,21 +12,14 @@ public class List { public record Query : IRequest; - public class QueryHandler : IRequestHandler + public class QueryHandler(ConduitContext context) : IRequestHandler { - private readonly ConduitContext _context; - - public QueryHandler(ConduitContext context) - { - _context = context; - } - public async Task Handle( Query message, CancellationToken cancellationToken ) { - var tags = await _context.Tags + var tags = await context.Tags .OrderBy(x => x.TagId) .AsNoTracking() .ToListAsync(cancellationToken); @@ -36,4 +29,4 @@ CancellationToken cancellationToken }; } } -} \ No newline at end of file +} diff --git a/src/Conduit/Features/Tags/TagsController.cs b/src/Conduit/Features/Tags/TagsController.cs index 5ec11a48..fce38d05 100644 --- a/src/Conduit/Features/Tags/TagsController.cs +++ b/src/Conduit/Features/Tags/TagsController.cs @@ -6,18 +6,8 @@ namespace Conduit.Features.Tags; [Route("tags")] -public class TagsController : Controller +public class TagsController(IMediator mediator) : Controller { - private readonly IMediator _mediator; - - public TagsController(IMediator mediator) - { - _mediator = mediator; - } - [HttpGet] - public Task Get(CancellationToken cancellationToken) - { - return _mediator.Send(new List.Query(), cancellationToken); - } -} \ No newline at end of file + public Task Get(CancellationToken cancellationToken) => mediator.Send(new List.Query(), cancellationToken); +} diff --git a/src/Conduit/Features/Users/Create.cs b/src/Conduit/Features/Users/Create.cs index a44b14b4..abe2c54c 100644 --- a/src/Conduit/Features/Users/Create.cs +++ b/src/Conduit/Features/Users/Create.cs @@ -16,14 +16,7 @@ namespace Conduit.Features.Users; public class Create { - public class UserData - { - public string? Username { get; set; } - - public string? Email { get; set; } - - public string? Password { get; set; } - } + public record UserData(string? Username, string? Email, string? Password); public record Command(UserData User) : IRequest; @@ -37,33 +30,20 @@ public CommandValidator() } } - public class Handler : IRequestHandler + public class Handler( + ConduitContext context, + IPasswordHasher passwordHasher, + IJwtTokenGenerator jwtTokenGenerator, + IMapper mapper) + : IRequestHandler { - private readonly ConduitContext _context; - private readonly IPasswordHasher _passwordHasher; - private readonly IJwtTokenGenerator _jwtTokenGenerator; - private readonly IMapper _mapper; - - public Handler( - ConduitContext context, - IPasswordHasher passwordHasher, - IJwtTokenGenerator jwtTokenGenerator, - IMapper mapper - ) - { - _context = context; - _passwordHasher = passwordHasher; - _jwtTokenGenerator = jwtTokenGenerator; - _mapper = mapper; - } - public async Task Handle( Command message, CancellationToken cancellationToken ) { if ( - await _context.Persons + await context.Persons .Where(x => x.Username == message.User.Username) .AnyAsync(cancellationToken) ) @@ -75,7 +55,7 @@ await _context.Persons } if ( - await _context.Persons + await context.Persons .Where(x => x.Email == message.User.Email) .AnyAsync(cancellationToken) ) @@ -91,21 +71,21 @@ await _context.Persons { Username = message.User.Username, Email = message.User.Email, - Hash = await _passwordHasher.Hash( + Hash = await passwordHasher.Hash( message.User.Password ?? throw new InvalidOperationException(), salt ), Salt = salt }; - await _context.Persons.AddAsync(person, cancellationToken); - await _context.SaveChangesAsync(cancellationToken); + await context.Persons.AddAsync(person, cancellationToken); + await context.SaveChangesAsync(cancellationToken); - var user = _mapper.Map(person); - user.Token = _jwtTokenGenerator.CreateToken( + var user = mapper.Map(person); + user.Token = jwtTokenGenerator.CreateToken( person.Username ?? throw new InvalidOperationException() ); return new UserEnvelope(user); } } -} \ No newline at end of file +} diff --git a/src/Conduit/Features/Users/Details.cs b/src/Conduit/Features/Users/Details.cs index 997c5f4c..427701cf 100644 --- a/src/Conduit/Features/Users/Details.cs +++ b/src/Conduit/Features/Users/Details.cs @@ -18,35 +18,21 @@ public record Query(string Username) : IRequest; public class QueryValidator : AbstractValidator { - public QueryValidator() - { - RuleFor(x => x.Username).NotNull().NotEmpty(); - } + public QueryValidator() => RuleFor(x => x.Username).NotNull().NotEmpty(); } - public class QueryHandler : IRequestHandler + public class QueryHandler( + ConduitContext context, + IJwtTokenGenerator jwtTokenGenerator, + IMapper mapper) + : IRequestHandler { - private readonly ConduitContext _context; - private readonly IJwtTokenGenerator _jwtTokenGenerator; - private readonly IMapper _mapper; - - public QueryHandler( - ConduitContext context, - IJwtTokenGenerator jwtTokenGenerator, - IMapper mapper - ) - { - _context = context; - _jwtTokenGenerator = jwtTokenGenerator; - _mapper = mapper; - } - public async Task Handle( Query message, CancellationToken cancellationToken ) { - var person = await _context.Persons + var person = await context.Persons .AsNoTracking() .FirstOrDefaultAsync(x => x.Username == message.Username, cancellationToken); @@ -58,11 +44,11 @@ CancellationToken cancellationToken ); } - var user = _mapper.Map(person); - user.Token = _jwtTokenGenerator.CreateToken( + var user = mapper.Map(person); + user.Token = jwtTokenGenerator.CreateToken( person.Username ?? throw new InvalidOperationException() ); return new UserEnvelope(user); } } -} \ No newline at end of file +} diff --git a/src/Conduit/Features/Users/Edit.cs b/src/Conduit/Features/Users/Edit.cs index e7fb845b..e78fea28 100644 --- a/src/Conduit/Features/Users/Edit.cs +++ b/src/Conduit/Features/Users/Edit.cs @@ -32,39 +32,23 @@ public record Command(UserData User) : IRequest; public class CommandValidator : AbstractValidator { - public CommandValidator() - { - RuleFor(x => x.User).NotNull(); - } + public CommandValidator() => RuleFor(x => x.User).NotNull(); } - public class Handler : IRequestHandler + public class Handler( + ConduitContext context, + IPasswordHasher passwordHasher, + ICurrentUserAccessor currentUserAccessor, + IMapper mapper) + : IRequestHandler { - private readonly ConduitContext _context; - private readonly IPasswordHasher _passwordHasher; - private readonly ICurrentUserAccessor _currentUserAccessor; - private readonly IMapper _mapper; - - public Handler( - ConduitContext context, - IPasswordHasher passwordHasher, - ICurrentUserAccessor currentUserAccessor, - IMapper mapper - ) - { - _context = context; - _passwordHasher = passwordHasher; - _currentUserAccessor = currentUserAccessor; - _mapper = mapper; - } - public async Task Handle( Command message, CancellationToken cancellationToken ) { - var currentUsername = _currentUserAccessor.GetCurrentUsername(); - var person = await _context.Persons + var currentUsername = currentUserAccessor.GetCurrentUsername(); + var person = await context.Persons .Where(x => x.Username == currentUsername) .FirstOrDefaultAsync(cancellationToken); if (person is null) @@ -83,13 +67,13 @@ CancellationToken cancellationToken if (!string.IsNullOrWhiteSpace(message.User.Password)) { var salt = Guid.NewGuid().ToByteArray(); - person.Hash = await _passwordHasher.Hash(message.User.Password, salt); + person.Hash = await passwordHasher.Hash(message.User.Password, salt); person.Salt = salt; } - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); - return new UserEnvelope(_mapper.Map(person)); + return new UserEnvelope(mapper.Map(person)); } } } diff --git a/src/Conduit/Features/Users/Login.cs b/src/Conduit/Features/Users/Login.cs index 3d80e9de..43dab254 100644 --- a/src/Conduit/Features/Users/Login.cs +++ b/src/Conduit/Features/Users/Login.cs @@ -17,9 +17,9 @@ public class Login { public class UserData { - public string? Email { get; set; } + public string? Email { get; init; } - public string? Password { get; set; } + public string? Password { get; init; } } public record Command(UserData User) : IRequest; @@ -34,32 +34,19 @@ public CommandValidator() } } - public class Handler : IRequestHandler + public class Handler( + ConduitContext context, + IPasswordHasher passwordHasher, + IJwtTokenGenerator jwtTokenGenerator, + IMapper mapper) + : IRequestHandler { - private readonly ConduitContext _context; - private readonly IPasswordHasher _passwordHasher; - private readonly IJwtTokenGenerator _jwtTokenGenerator; - private readonly IMapper _mapper; - - public Handler( - ConduitContext context, - IPasswordHasher passwordHasher, - IJwtTokenGenerator jwtTokenGenerator, - IMapper mapper - ) - { - _context = context; - _passwordHasher = passwordHasher; - _jwtTokenGenerator = jwtTokenGenerator; - _mapper = mapper; - } - public async Task Handle( Command message, CancellationToken cancellationToken ) { - var person = await _context.Persons + var person = await context.Persons .Where(x => x.Email == message.User.Email) .SingleOrDefaultAsync(cancellationToken); if (person == null) @@ -72,7 +59,7 @@ CancellationToken cancellationToken if ( !person.Hash.SequenceEqual( - await _passwordHasher.Hash( + await passwordHasher.Hash( message.User.Password ?? throw new InvalidOperationException(), person.Salt ) @@ -85,11 +72,11 @@ await _passwordHasher.Hash( ); } - var user = _mapper.Map(person); - user.Token = _jwtTokenGenerator.CreateToken( + var user = mapper.Map(person); + user.Token = jwtTokenGenerator.CreateToken( person.Username ?? throw new InvalidOperationException() ); return new UserEnvelope(user); } } -} \ No newline at end of file +} diff --git a/src/Conduit/Features/Users/MappingProfile.cs b/src/Conduit/Features/Users/MappingProfile.cs index eeef93d0..46e8116a 100644 --- a/src/Conduit/Features/Users/MappingProfile.cs +++ b/src/Conduit/Features/Users/MappingProfile.cs @@ -4,8 +4,5 @@ namespace Conduit.Features.Users; public class MappingProfile : Profile { - public MappingProfile() - { - CreateMap(MemberList.None); - } + public MappingProfile() => CreateMap(MemberList.None); } \ No newline at end of file diff --git a/src/Conduit/Features/Users/User.cs b/src/Conduit/Features/Users/User.cs index 6df19bd4..19e8944c 100644 --- a/src/Conduit/Features/Users/User.cs +++ b/src/Conduit/Features/Users/User.cs @@ -2,13 +2,13 @@ namespace Conduit.Features.Users; public class User { - public string? Username { get; set; } + public string? Username { get; init; } - public string? Email { get; set; } + public string? Email { get; init; } - public string? Bio { get; set; } + public string? Bio { get; init; } - public string? Image { get; set; } + public string? Image { get; init; } public string? Token { get; set; } } diff --git a/src/Conduit/Features/Users/UserController.cs b/src/Conduit/Features/Users/UserController.cs index ec6999dc..81308ba6 100644 --- a/src/Conduit/Features/Users/UserController.cs +++ b/src/Conduit/Features/Users/UserController.cs @@ -10,32 +10,19 @@ namespace Conduit.Features.Users; [Route("user")] [Authorize(AuthenticationSchemes = JwtIssuerOptions.Schemes)] -public class UserController +public class UserController(IMediator mediator, ICurrentUserAccessor currentUserAccessor) { - private readonly IMediator _mediator; - private readonly ICurrentUserAccessor _currentUserAccessor; - - public UserController(IMediator mediator, ICurrentUserAccessor currentUserAccessor) - { - _mediator = mediator; - _currentUserAccessor = currentUserAccessor; - } - [HttpGet] - public Task GetCurrent(CancellationToken cancellationToken) - { - return _mediator.Send( - new Details.Query(_currentUserAccessor.GetCurrentUsername() ?? ""), + public Task GetCurrent(CancellationToken cancellationToken) => + mediator.Send( + new Details.Query(currentUserAccessor.GetCurrentUsername() ?? ""), cancellationToken ); - } [HttpPut] public Task UpdateUser( [FromBody] Edit.Command command, CancellationToken cancellationToken - ) - { - return _mediator.Send(command, cancellationToken); - } -} \ No newline at end of file + ) => + mediator.Send(command, cancellationToken); +} diff --git a/src/Conduit/Features/Users/UsersController.cs b/src/Conduit/Features/Users/UsersController.cs index 8e78c0f3..e7a10d8c 100644 --- a/src/Conduit/Features/Users/UsersController.cs +++ b/src/Conduit/Features/Users/UsersController.cs @@ -6,21 +6,17 @@ namespace Conduit.Features.Users; [Route("users")] -public class UsersController +public class UsersController(IMediator mediator) { - private readonly IMediator _mediator; - - public UsersController(IMediator mediator) => _mediator = mediator; - [HttpPost] public Task Create( [FromBody] Create.Command command, CancellationToken cancellationToken - ) => _mediator.Send(command, cancellationToken); + ) => mediator.Send(command, cancellationToken); [HttpPost("login")] public Task Login( [FromBody] Login.Command command, CancellationToken cancellationToken - ) => _mediator.Send(command, cancellationToken); -} \ No newline at end of file + ) => mediator.Send(command, cancellationToken); +} diff --git a/src/Conduit/Infrastructure/ConduitContext.cs b/src/Conduit/Infrastructure/ConduitContext.cs index 0e14f06b..77cea5de 100644 --- a/src/Conduit/Infrastructure/ConduitContext.cs +++ b/src/Conduit/Infrastructure/ConduitContext.cs @@ -5,20 +5,17 @@ namespace Conduit.Infrastructure; -public class ConduitContext : DbContext +public class ConduitContext(DbContextOptions options) : DbContext(options) { private IDbContextTransaction? _currentTransaction; - public ConduitContext(DbContextOptions options) - : base(options) { } - - public DbSet
Articles { get; set; } = null!; - public DbSet Comments { get; set; } = null!; - public DbSet Persons { get; set; } = null!; - public DbSet Tags { get; set; } = null!; - public DbSet ArticleTags { get; set; } = null!; - public DbSet ArticleFavorites { get; set; } = null!; - public DbSet FollowedPeople { get; set; } = null!; + public DbSet
Articles { get; init; } = null!; + public DbSet Comments { get; init; } = null!; + public DbSet Persons { get; init; } = null!; + public DbSet Tags { get; init; } = null!; + public DbSet ArticleTags { get; init; } = null!; + public DbSet ArticleFavorites { get; init; } = null!; + public DbSet FollowedPeople { get; init; } = null!; protected override void OnModelCreating(ModelBuilder modelBuilder) { @@ -27,10 +24,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) b.HasKey(t => new { t.ArticleId, t.TagId }); b.HasOne(pt => pt.Article) - .WithMany(p => p!.ArticleTags) + .WithMany(p => p.ArticleTags) .HasForeignKey(pt => pt.ArticleId); - b.HasOne(pt => pt.Tag).WithMany(t => t!.ArticleTags).HasForeignKey(pt => pt.TagId); + b.HasOne(pt => pt.Tag).WithMany(t => t.ArticleTags).HasForeignKey(pt => pt.TagId); }); modelBuilder.Entity(b => @@ -38,11 +35,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) b.HasKey(t => new { t.ArticleId, t.PersonId }); b.HasOne(pt => pt.Article) - .WithMany(p => p!.ArticleFavorites) + .WithMany(p => p.ArticleFavorites) .HasForeignKey(pt => pt.ArticleId); b.HasOne(pt => pt.Person) - .WithMany(t => t!.ArticleFavorites) + .WithMany(t => t.ArticleFavorites) .HasForeignKey(pt => pt.PersonId); }); @@ -57,7 +54,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) // Message = Introducing FOREIGN KEY constraint 'FK_FollowedPeople_Persons_TargetId' on table 'FollowedPeople' may cause cycles or multiple cascade paths.Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. // Could not create constraint or index. See previous errors. b.HasOne(pt => pt.Observer) - .WithMany(p => p!.Followers) + .WithMany(p => p.Followers) .HasForeignKey(pt => pt.ObserverId) .OnDelete(DeleteBehavior.Restrict); @@ -68,7 +65,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) // Message = Introducing FOREIGN KEY constraint 'FK_FollowingPeople_Persons_TargetId' on table 'FollowedPeople' may cause cycles or multiple cascade paths.Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. // Could not create constraint or index. See previous errors. b.HasOne(pt => pt.Target) - .WithMany(t => t!.Following) + .WithMany(t => t.Following) .HasForeignKey(pt => pt.TargetId) .OnDelete(DeleteBehavior.Restrict); }); @@ -125,4 +122,4 @@ public void RollbackTransaction() } } #endregion -} \ No newline at end of file +} diff --git a/src/Conduit/Infrastructure/CurrentUserAccessor.cs b/src/Conduit/Infrastructure/CurrentUserAccessor.cs index e198fd9f..e520004f 100644 --- a/src/Conduit/Infrastructure/CurrentUserAccessor.cs +++ b/src/Conduit/Infrastructure/CurrentUserAccessor.cs @@ -4,19 +4,10 @@ namespace Conduit.Infrastructure; -public class CurrentUserAccessor : ICurrentUserAccessor +public class CurrentUserAccessor(IHttpContextAccessor httpContextAccessor) : ICurrentUserAccessor { - private readonly IHttpContextAccessor _httpContextAccessor; - - public CurrentUserAccessor(IHttpContextAccessor httpContextAccessor) - { - _httpContextAccessor = httpContextAccessor; - } - - public string? GetCurrentUsername() - { - return _httpContextAccessor.HttpContext - ?.User?.Claims?.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier) + public string? GetCurrentUsername() => + httpContextAccessor.HttpContext + ?.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier) ?.Value; - } -} \ No newline at end of file +} diff --git a/src/Conduit/Infrastructure/DBContextTransactionPipelineBehavior.cs b/src/Conduit/Infrastructure/DBContextTransactionPipelineBehavior.cs index 63ff1f60..7b44f3a8 100644 --- a/src/Conduit/Infrastructure/DBContextTransactionPipelineBehavior.cs +++ b/src/Conduit/Infrastructure/DBContextTransactionPipelineBehavior.cs @@ -10,36 +10,32 @@ namespace Conduit.Infrastructure; /// /// /// -public class DBContextTransactionPipelineBehavior +public class DBContextTransactionPipelineBehavior(ConduitContext context) : IPipelineBehavior where TRequest : notnull { - private readonly ConduitContext _context; - - public DBContextTransactionPipelineBehavior(ConduitContext context) => _context = context; - public async Task Handle( TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken ) { - TResponse? result = default; + TResponse? result; try { - _context.BeginTransaction(); + context.BeginTransaction(); result = await next(); - _context.CommitTransaction(); + context.CommitTransaction(); } catch (Exception) { - _context.RollbackTransaction(); + context.RollbackTransaction(); throw; } return result; } -} \ No newline at end of file +} diff --git a/src/Conduit/Infrastructure/Errors/ErrorHandlingMiddleware.cs b/src/Conduit/Infrastructure/Errors/ErrorHandlingMiddleware.cs index fcd19956..ddbb1742 100644 --- a/src/Conduit/Infrastructure/Errors/ErrorHandlingMiddleware.cs +++ b/src/Conduit/Infrastructure/Errors/ErrorHandlingMiddleware.cs @@ -8,11 +8,11 @@ namespace Conduit.Infrastructure.Errors; -public class ErrorHandlingMiddleware +public class ErrorHandlingMiddleware( + RequestDelegate next, + IStringLocalizer localizer, + ILogger logger) { - private readonly RequestDelegate _next; - private readonly ILogger _logger; - private readonly IStringLocalizer _localizer; private static readonly Action LOGGER_MESSAGE = LoggerMessage.Define( LogLevel.Error, @@ -20,26 +20,15 @@ public class ErrorHandlingMiddleware formatString: "{Message}" ); - public ErrorHandlingMiddleware( - RequestDelegate next, - IStringLocalizer localizer, - ILogger logger - ) - { - _next = next; - _logger = logger; - _localizer = localizer; - } - public async Task Invoke(HttpContext context) { try { - await _next(context); + await next(context); } catch (Exception ex) { - await HandleExceptionAsync(context, ex, _logger, _localizer); + await HandleExceptionAsync(context, ex, logger, localizer); } } @@ -50,25 +39,23 @@ private static async Task HandleExceptionAsync( IStringLocalizer localizer ) { - string? result = null; + string? result; switch (exception) { case RestException re: context.Response.StatusCode = (int)re.Code; result = JsonSerializer.Serialize(new { errors = re.Errors }); break; - case Exception e: + default: context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; - LOGGER_MESSAGE(logger, "Unhandled Exception", e); + LOGGER_MESSAGE(logger, "Unhandled Exception", exception); result = JsonSerializer.Serialize( new { errors = localizer[Constants.InternalServerError].Value } ); break; - default: - break; } context.Response.ContentType = "application/json"; - await context.Response.WriteAsync(result ?? "{}"); + await context.Response.WriteAsync(result); } -} \ No newline at end of file +} diff --git a/src/Conduit/Infrastructure/Errors/RestException.cs b/src/Conduit/Infrastructure/Errors/RestException.cs index d61a61a8..2e6aed96 100644 --- a/src/Conduit/Infrastructure/Errors/RestException.cs +++ b/src/Conduit/Infrastructure/Errors/RestException.cs @@ -3,15 +3,9 @@ namespace Conduit.Infrastructure.Errors; -public class RestException : Exception +public class RestException(HttpStatusCode code, object? errors = null) : Exception { - public RestException(HttpStatusCode code, object? errors = null) - { - Code = code; - Errors = errors; - } + public object? Errors { get; } = errors; - public object? Errors { get; set; } - - public HttpStatusCode Code { get; } -} \ No newline at end of file + public HttpStatusCode Code { get; } = code; +} diff --git a/src/Conduit/Infrastructure/Security/JwtTokenGenerator.cs b/src/Conduit/Infrastructure/Security/JwtTokenGenerator.cs index b5cee5af..e2041f1c 100644 --- a/src/Conduit/Infrastructure/Security/JwtTokenGenerator.cs +++ b/src/Conduit/Infrastructure/Security/JwtTokenGenerator.cs @@ -5,14 +5,9 @@ namespace Conduit.Infrastructure.Security; -public class JwtTokenGenerator : IJwtTokenGenerator +public class JwtTokenGenerator(IOptions jwtOptions) : IJwtTokenGenerator { - private readonly JwtIssuerOptions _jwtOptions; - - public JwtTokenGenerator(IOptions jwtOptions) - { - _jwtOptions = jwtOptions.Value; - } + private readonly JwtIssuerOptions _jwtOptions = jwtOptions.Value; public string CreateToken(string username) { @@ -38,4 +33,4 @@ public string CreateToken(string username) var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt); return encodedJwt; } -} \ No newline at end of file +} diff --git a/src/Conduit/Infrastructure/ValidationPipelineBehavior.cs b/src/Conduit/Infrastructure/ValidationPipelineBehavior.cs index f10058e0..dd25956c 100644 --- a/src/Conduit/Infrastructure/ValidationPipelineBehavior.cs +++ b/src/Conduit/Infrastructure/ValidationPipelineBehavior.cs @@ -7,14 +7,11 @@ namespace Conduit.Infrastructure; -public class ValidationPipelineBehavior +public class ValidationPipelineBehavior(IEnumerable> validators) : IPipelineBehavior where TRequest : notnull { - private readonly List> _validators; - - public ValidationPipelineBehavior(IEnumerable> validators) => - _validators = validators.ToList(); + private readonly List> _validators = validators.ToList(); public async Task Handle( TRequest request, @@ -36,4 +33,4 @@ CancellationToken cancellationToken return await next(); } -} \ No newline at end of file +} diff --git a/src/Conduit/StartupExtensions.cs b/src/Conduit/StartupExtensions.cs index 74197fa9..13690184 100644 --- a/src/Conduit/StartupExtensions.cs +++ b/src/Conduit/StartupExtensions.cs @@ -60,10 +60,9 @@ public static void AddJwt(this IServiceCollection services) { OnMessageReceived = (context) => { - var token = context.HttpContext.Request.Headers["Authorization"].ToString(); + var token = context.HttpContext.Request.Headers.Authorization.ToString(); if ( - token is not null - && token.StartsWith("Token ", StringComparison.OrdinalIgnoreCase) + token.StartsWith("Token ", StringComparison.OrdinalIgnoreCase) ) { context.Token = token["Token ".Length..].Trim(); diff --git a/tests/Conduit.IntegrationTests/Features/Articles/CreateTests.cs b/tests/Conduit.IntegrationTests/Features/Articles/CreateTests.cs index ed266d4f..9c8c175d 100644 --- a/tests/Conduit.IntegrationTests/Features/Articles/CreateTests.cs +++ b/tests/Conduit.IntegrationTests/Features/Articles/CreateTests.cs @@ -16,7 +16,7 @@ public async Task Expect_Create_Article() Title = "Test article dsergiu77", Description = "Description of the test article", Body = "Body of the test article", - TagList = new string[] { "tag1", "tag2" } + TagList = ["tag1", "tag2"] } ); diff --git a/tests/Conduit.IntegrationTests/Features/Articles/DeleteTests.cs b/tests/Conduit.IntegrationTests/Features/Articles/DeleteTests.cs index a88d7f67..eed88add 100644 --- a/tests/Conduit.IntegrationTests/Features/Articles/DeleteTests.cs +++ b/tests/Conduit.IntegrationTests/Features/Articles/DeleteTests.cs @@ -49,7 +49,7 @@ public async Task Expect_Delete_Article_With_Tags() Title = "Test article dsergiu77", Description = "Description of the test article", Body = "Body of the test article", - TagList = new string[] { "tag1", "tag2" } + TagList = ["tag1", "tag2"] } ); diff --git a/tests/Conduit.IntegrationTests/Features/Articles/EditTests.cs b/tests/Conduit.IntegrationTests/Features/Articles/EditTests.cs index 018850c6..46ef80e2 100644 --- a/tests/Conduit.IntegrationTests/Features/Articles/EditTests.cs +++ b/tests/Conduit.IntegrationTests/Features/Articles/EditTests.cs @@ -17,7 +17,7 @@ public async Task Expect_Edit_Article() Title = "Test article dsergiu77", Description = "Description of the test article", Body = "Body of the test article", - TagList = new string[] { "tag1", "tag2" } + TagList = ["tag1", "tag2"] } ); @@ -25,17 +25,10 @@ public async Task Expect_Edit_Article() var command = new Edit.Command( new( - new Edit.ArticleData() - { - Title = "Updated " + createdArticle.Title, - Description = "Updated" + createdArticle.Description, - Body = "Updated" + createdArticle.Body, - } - ), + new Edit.ArticleData("Updated " + createdArticle.Title, "Updated " + createdArticle.Description, "Updated " + createdArticle.Body, + [createdArticle.TagList[1], "tag3"])), createdArticle.Slug ?? throw new InvalidOperationException() ); - // remove the first tag and add a new tag - command.Model.Article.TagList = new string[] { createdArticle.TagList[1], "tag3" }; var dbContext = GetDbContext(); @@ -47,9 +40,9 @@ public async Task Expect_Edit_Article() Assert.NotNull(edited); Assert.Equal(edited.Article.Title, command.Model.Article.Title); - Assert.Equal(edited.Article.TagList.Count(), command.Model.Article.TagList.Count()); + Assert.Equal(edited.Article.TagList.Count, command.Model.Article.TagList?.Count() ?? 0); // use assert Contains because we do not know the order in which the tags are saved/retrieved - Assert.Contains(edited.Article.TagList[0], command.Model.Article.TagList); - Assert.Contains(edited.Article.TagList[1], command.Model.Article.TagList); + Assert.Contains(edited.Article.TagList[0], command.Model.Article.TagList ?? []); + Assert.Contains(edited.Article.TagList[1], command.Model.Article.TagList?? []); } } diff --git a/tests/Conduit.IntegrationTests/Features/Users/CreateTests.cs b/tests/Conduit.IntegrationTests/Features/Users/CreateTests.cs index bd3b0c90..9bec2334 100644 --- a/tests/Conduit.IntegrationTests/Features/Users/CreateTests.cs +++ b/tests/Conduit.IntegrationTests/Features/Users/CreateTests.cs @@ -13,12 +13,7 @@ public class CreateTests : SliceFixture public async Task Expect_Create_User() { var command = new Create.Command( - new Create.UserData() - { - Email = "email", - Password = "password", - Username = "username" - } + new Create.UserData("username", "email", "password") ); await SendAsync(command); @@ -30,4 +25,4 @@ public async Task Expect_Create_User() Assert.NotNull(created); Assert.Equal(created.Hash, await new PasswordHasher().Hash("password", created.Salt)); } -} \ No newline at end of file +} diff --git a/tests/Conduit.IntegrationTests/Features/Users/UserHelpers.cs b/tests/Conduit.IntegrationTests/Features/Users/UserHelpers.cs index 5529a2fa..f445294e 100644 --- a/tests/Conduit.IntegrationTests/Features/Users/UserHelpers.cs +++ b/tests/Conduit.IntegrationTests/Features/Users/UserHelpers.cs @@ -15,15 +15,10 @@ public static class UserHelpers public static async Task CreateDefaultUser(SliceFixture fixture) { var command = new Create.Command( - new Create.UserData() - { - Email = "email", - Password = "password", - Username = DefaultUserName - } + new Create.UserData(DefaultUserName, "email", "password") ); var commandResult = await fixture.SendAsync(command); return commandResult.User; } -} \ No newline at end of file +} diff --git a/tests/Conduit.IntegrationTests/StubCurrentUserAccessor.cs b/tests/Conduit.IntegrationTests/StubCurrentUserAccessor.cs index 6cb2ef1c..03108dc5 100644 --- a/tests/Conduit.IntegrationTests/StubCurrentUserAccessor.cs +++ b/tests/Conduit.IntegrationTests/StubCurrentUserAccessor.cs @@ -2,15 +2,7 @@ namespace Conduit.IntegrationTests; -public class StubCurrentUserAccessor : ICurrentUserAccessor +public class StubCurrentUserAccessor(string userName) : ICurrentUserAccessor { - private readonly string _currentUserName; - - /// - /// stub the ICurrentUserAccessor with a given userName to be used in tests - /// - /// - public StubCurrentUserAccessor(string userName) => _currentUserName = userName; - - public string GetCurrentUsername() => _currentUserName; -} \ No newline at end of file + public string GetCurrentUsername() => userName; +}