Style: C# 12 Primary constructor
This commit is contained in:
@@ -5,19 +5,12 @@ using Hutopy.Application.Common.Security;
|
||||
|
||||
namespace Hutopy.Application.Common.Behaviours;
|
||||
|
||||
public class AuthorizationBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : notnull
|
||||
public class AuthorizationBehaviour<TRequest, TResponse>(
|
||||
IUser user,
|
||||
IIdentityService identityService)
|
||||
: IPipelineBehavior<TRequest, TResponse>
|
||||
where TRequest : notnull
|
||||
{
|
||||
private readonly IUser _user;
|
||||
private readonly IIdentityService _identityService;
|
||||
|
||||
public AuthorizationBehaviour(
|
||||
IUser user,
|
||||
IIdentityService identityService)
|
||||
{
|
||||
_user = user;
|
||||
_identityService = identityService;
|
||||
}
|
||||
|
||||
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
|
||||
{
|
||||
var authorizeAttributes = request.GetType().GetCustomAttributes<AuthorizeAttribute>();
|
||||
@@ -25,7 +18,7 @@ public class AuthorizationBehaviour<TRequest, TResponse> : IPipelineBehavior<TRe
|
||||
if (authorizeAttributes.Any())
|
||||
{
|
||||
// Must be authenticated user
|
||||
if (_user.Id == null)
|
||||
if (user.Id == null)
|
||||
{
|
||||
throw new UnauthorizedAccessException();
|
||||
}
|
||||
@@ -41,7 +34,7 @@ public class AuthorizationBehaviour<TRequest, TResponse> : IPipelineBehavior<TRe
|
||||
{
|
||||
foreach (var role in roles)
|
||||
{
|
||||
var isInRole = await _identityService.IsInRoleAsync(_user.Id, role.Trim());
|
||||
var isInRole = await identityService.IsInRoleAsync(user.Id, role.Trim());
|
||||
if (isInRole)
|
||||
{
|
||||
authorized = true;
|
||||
@@ -63,7 +56,7 @@ public class AuthorizationBehaviour<TRequest, TResponse> : IPipelineBehavior<TRe
|
||||
{
|
||||
foreach (var policy in authorizeAttributesWithPolicies.Select(a => a.Policy))
|
||||
{
|
||||
var authorized = await _identityService.AuthorizeAsync(_user.Id, policy);
|
||||
var authorized = await identityService.AuthorizeAsync(user.Id, policy);
|
||||
|
||||
if (!authorized)
|
||||
{
|
||||
|
||||
@@ -4,28 +4,24 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Hutopy.Application.Common.Behaviours;
|
||||
|
||||
public class LoggingBehaviour<TRequest> : IRequestPreProcessor<TRequest> where TRequest : notnull
|
||||
public class LoggingBehaviour<TRequest>(
|
||||
ILogger<TRequest> logger,
|
||||
IUser user,
|
||||
IIdentityService identityService)
|
||||
: IRequestPreProcessor<TRequest>
|
||||
where TRequest : notnull
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IUser _user;
|
||||
private readonly IIdentityService _identityService;
|
||||
|
||||
public LoggingBehaviour(ILogger<TRequest> logger, IUser user, IIdentityService identityService)
|
||||
{
|
||||
_logger = logger;
|
||||
_user = user;
|
||||
_identityService = identityService;
|
||||
}
|
||||
private readonly ILogger _logger = logger;
|
||||
|
||||
public async Task Process(TRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var requestName = typeof(TRequest).Name;
|
||||
var userId = _user.Id ?? string.Empty;
|
||||
var userId = user.Id ?? string.Empty;
|
||||
string? userName = string.Empty;
|
||||
|
||||
if (!string.IsNullOrEmpty(userId))
|
||||
{
|
||||
userName = await _identityService.GetUserNameAsync(userId);
|
||||
userName = await identityService.GetUserNameAsync(userId);
|
||||
}
|
||||
|
||||
_logger.LogInformation("Hutopy Request: {Name} {@UserId} {@UserName} {@Request}",
|
||||
|
||||
@@ -4,24 +4,14 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Hutopy.Application.Common.Behaviours;
|
||||
|
||||
public class PerformanceBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : notnull
|
||||
public class PerformanceBehaviour<TRequest, TResponse>(
|
||||
ILogger<TRequest> logger,
|
||||
IUser user,
|
||||
IIdentityService identityService)
|
||||
: IPipelineBehavior<TRequest, TResponse>
|
||||
where TRequest : notnull
|
||||
{
|
||||
private readonly Stopwatch _timer;
|
||||
private readonly ILogger<TRequest> _logger;
|
||||
private readonly IUser _user;
|
||||
private readonly IIdentityService _identityService;
|
||||
|
||||
public PerformanceBehaviour(
|
||||
ILogger<TRequest> logger,
|
||||
IUser user,
|
||||
IIdentityService identityService)
|
||||
{
|
||||
_timer = new Stopwatch();
|
||||
|
||||
_logger = logger;
|
||||
_user = user;
|
||||
_identityService = identityService;
|
||||
}
|
||||
private readonly Stopwatch _timer = new();
|
||||
|
||||
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
|
||||
{
|
||||
@@ -33,20 +23,16 @@ public class PerformanceBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequ
|
||||
|
||||
var elapsedMilliseconds = _timer.ElapsedMilliseconds;
|
||||
|
||||
if (elapsedMilliseconds > 500)
|
||||
{
|
||||
var requestName = typeof(TRequest).Name;
|
||||
var userId = _user.Id ?? string.Empty;
|
||||
var userName = string.Empty;
|
||||
if (elapsedMilliseconds <= 500) return response;
|
||||
|
||||
if (!string.IsNullOrEmpty(userId))
|
||||
{
|
||||
userName = await _identityService.GetUserNameAsync(userId);
|
||||
}
|
||||
var requestName = typeof(TRequest).Name;
|
||||
var userId = user.Id ?? string.Empty;
|
||||
var userName = string.Empty;
|
||||
|
||||
_logger.LogWarning("Hutopy Long Running Request: {Name} ({ElapsedMilliseconds} milliseconds) {@UserId} {@UserName} {@Request}",
|
||||
requestName, elapsedMilliseconds, userId, userName, request);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(userId)) userName = await identityService.GetUserNameAsync(userId);
|
||||
|
||||
logger.LogWarning("Hutopy Long Running Request: {Name} ({ElapsedMilliseconds} milliseconds) {@UserId} {@UserName} {@Request}",
|
||||
requestName, elapsedMilliseconds, userId, userName, request);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -2,15 +2,11 @@
|
||||
|
||||
namespace Hutopy.Application.Common.Behaviours;
|
||||
|
||||
public class UnhandledExceptionBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : notnull
|
||||
public class UnhandledExceptionBehaviour<TRequest, TResponse>(
|
||||
ILogger<TRequest> logger)
|
||||
: IPipelineBehavior<TRequest, TResponse>
|
||||
where TRequest : notnull
|
||||
{
|
||||
private readonly ILogger<TRequest> _logger;
|
||||
|
||||
public UnhandledExceptionBehaviour(ILogger<TRequest> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
@@ -21,7 +17,7 @@ public class UnhandledExceptionBehaviour<TRequest, TResponse> : IPipelineBehavio
|
||||
{
|
||||
var requestName = typeof(TRequest).Name;
|
||||
|
||||
_logger.LogError(ex, "Hutopy Request: Unhandled Exception for Request {Name} {@Request}", requestName, request);
|
||||
logger.LogError(ex, "Hutopy Request: Unhandled Exception for Request {Name} {@Request}", requestName, request);
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
@@ -2,34 +2,27 @@
|
||||
|
||||
namespace Hutopy.Application.Common.Behaviours;
|
||||
|
||||
public class ValidationBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
|
||||
where TRequest : notnull
|
||||
public class ValidationBehaviour<TRequest, TResponse>(IEnumerable<IValidator<TRequest>> validators)
|
||||
: IPipelineBehavior<TRequest, TResponse>
|
||||
where TRequest : notnull
|
||||
{
|
||||
private readonly IEnumerable<IValidator<TRequest>> _validators;
|
||||
|
||||
public ValidationBehaviour(IEnumerable<IValidator<TRequest>> validators)
|
||||
{
|
||||
_validators = validators;
|
||||
}
|
||||
|
||||
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
|
||||
{
|
||||
if (_validators.Any())
|
||||
{
|
||||
var context = new ValidationContext<TRequest>(request);
|
||||
if (!validators.Any()) return await next();
|
||||
|
||||
var validationResults = await Task.WhenAll(
|
||||
_validators.Select(v =>
|
||||
v.ValidateAsync(context, cancellationToken)));
|
||||
var context = new ValidationContext<TRequest>(request);
|
||||
|
||||
var failures = validationResults
|
||||
.Where(r => r.Errors.Any())
|
||||
.SelectMany(r => r.Errors)
|
||||
.ToList();
|
||||
var validationResults = await Task.WhenAll(
|
||||
validators.Select(v =>
|
||||
v.ValidateAsync(context, cancellationToken)));
|
||||
|
||||
if (failures.Any())
|
||||
throw new ValidationException(failures);
|
||||
}
|
||||
var failures = validationResults
|
||||
.Where(r => r.Errors.Any())
|
||||
.SelectMany(r => r.Errors)
|
||||
.ToList();
|
||||
|
||||
if (failures.Count != 0) throw new ValidationException(failures);
|
||||
|
||||
return await next();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,9 @@
|
||||
|
||||
namespace Hutopy.Application.Common.Exceptions;
|
||||
|
||||
public class ValidationException : Exception
|
||||
public class ValidationException()
|
||||
: Exception("One or more validation failures have occurred.")
|
||||
{
|
||||
public ValidationException()
|
||||
: base("One or more validation failures have occurred.")
|
||||
{
|
||||
Errors = new Dictionary<string, string[]>();
|
||||
}
|
||||
|
||||
public ValidationException(IEnumerable<ValidationFailure> failures)
|
||||
: this()
|
||||
{
|
||||
@@ -18,5 +13,5 @@ public class ValidationException : Exception
|
||||
.ToDictionary(failureGroup => failureGroup.Key, failureGroup => failureGroup.ToArray());
|
||||
}
|
||||
|
||||
public IDictionary<string, string[]> Errors { get; }
|
||||
public IDictionary<string, string[]> Errors { get; } = new Dictionary<string, string[]>();
|
||||
}
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
namespace Hutopy.Application.Common.Models;
|
||||
|
||||
public class PaginatedList<T>
|
||||
public class PaginatedList<T>(
|
||||
IReadOnlyCollection<T> items,
|
||||
int count,
|
||||
int pageNumber,
|
||||
int pageSize)
|
||||
{
|
||||
public IReadOnlyCollection<T> Items { get; }
|
||||
public int PageNumber { get; }
|
||||
public int TotalPages { get; }
|
||||
public int TotalCount { get; }
|
||||
|
||||
public PaginatedList(IReadOnlyCollection<T> items, int count, int pageNumber, int pageSize)
|
||||
{
|
||||
PageNumber = pageNumber;
|
||||
TotalPages = (int)Math.Ceiling(count / (double)pageSize);
|
||||
TotalCount = count;
|
||||
Items = items;
|
||||
}
|
||||
public IReadOnlyCollection<T> Items { get; } = items;
|
||||
public int PageNumber { get; } = pageNumber;
|
||||
public int TotalPages { get; } = (int)Math.Ceiling(count / (double)pageSize);
|
||||
public int TotalCount { get; } = count;
|
||||
|
||||
public bool HasPreviousPage => PageNumber > 1;
|
||||
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
namespace Hutopy.Application.Common.Models;
|
||||
|
||||
public class Result
|
||||
public class Result(
|
||||
bool succeeded,
|
||||
IEnumerable<string> errors)
|
||||
{
|
||||
internal Result(bool succeeded, IEnumerable<string> errors)
|
||||
{
|
||||
Succeeded = succeeded;
|
||||
Errors = errors.ToArray();
|
||||
}
|
||||
public bool Succeeded { get; init; } = succeeded;
|
||||
|
||||
public bool Succeeded { get; init; }
|
||||
|
||||
public string[] Errors { get; init; }
|
||||
public string[] Errors { get; init; } = errors.ToArray();
|
||||
|
||||
public static Result Success()
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/// <summary>
|
||||
/// Specifies the class this attribute is applied to requires authorization.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
|
||||
public class AuthorizeAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection;
|
||||
namespace Hutopy.Application;
|
||||
|
||||
public static class DependencyInjection
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@ using Hutopy.Domain.Entities;
|
||||
|
||||
namespace Hutopy.Application.FutureCreators.Commands;
|
||||
|
||||
public record CreateFutureCreatorCommand : IRequest<int>
|
||||
public abstract record CreateFutureCreatorCommand : IRequest<int>
|
||||
{
|
||||
public required string FirstName { get; init; }
|
||||
public required string LastName { get; init; }
|
||||
@@ -13,16 +13,10 @@ public record CreateFutureCreatorCommand : IRequest<int>
|
||||
public required string ReasonToJoin { get; init; }
|
||||
}
|
||||
|
||||
public class CreateFuturCreatorCommandHandler : IRequestHandler<CreateFutureCreatorCommand, int>
|
||||
public class CreateFutureCreatorCommandHandler(
|
||||
IApplicationDbContext context)
|
||||
: IRequestHandler<CreateFutureCreatorCommand, int>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
|
||||
public CreateFuturCreatorCommandHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<int> Handle(CreateFutureCreatorCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = new FutureCreator
|
||||
@@ -35,9 +29,9 @@ public class CreateFuturCreatorCommandHandler : IRequestHandler<CreateFutureCrea
|
||||
ReasonToJoin = request.ReasonToJoin,
|
||||
};
|
||||
|
||||
_context.FutureCreators.Add(entity);
|
||||
context.FutureCreators.Add(entity);
|
||||
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
await context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return entity.Id;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
|
||||
namespace Hutopy.Application.Stripe.Commands;
|
||||
public record CreateSessionCheckoutCommand : IRequest<string>
|
||||
public abstract record CreateSessionCheckoutCommand : IRequest<string>
|
||||
{
|
||||
public required int Price { get; init; }
|
||||
|
||||
@@ -10,21 +10,16 @@ public record CreateSessionCheckoutCommand : IRequest<string>
|
||||
}
|
||||
|
||||
|
||||
public class CreateSessionCheckoutCommandHandler : IRequestHandler<CreateSessionCheckoutCommand, string>
|
||||
public class CreateSessionCheckoutCommandHandler(
|
||||
IApplicationDbContext context,
|
||||
IStripeService stripeService)
|
||||
: IRequestHandler<CreateSessionCheckoutCommand, string>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
private readonly IStripeService _stripeService;
|
||||
|
||||
|
||||
public CreateSessionCheckoutCommandHandler(IApplicationDbContext context, IStripeService stripeService)
|
||||
{
|
||||
_context = context;
|
||||
_stripeService = stripeService;
|
||||
}
|
||||
|
||||
private readonly IApplicationDbContext _context = context;
|
||||
|
||||
public async Task<string> Handle(CreateSessionCheckoutCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var stripeSecret = await _stripeService.CreateCheckoutSession(request.Price, request.Currency);
|
||||
var stripeSecret = await stripeService.CreateCheckoutSession(request.Price, request.Currency);
|
||||
|
||||
return stripeSecret;
|
||||
}
|
||||
|
||||
@@ -11,15 +11,10 @@ public record CreateTodoItemCommand : IRequest<int>
|
||||
public string? Title { get; init; }
|
||||
}
|
||||
|
||||
public class CreateTodoItemCommandHandler : IRequestHandler<CreateTodoItemCommand, int>
|
||||
public class CreateTodoItemCommandHandler(
|
||||
IApplicationDbContext context)
|
||||
: IRequestHandler<CreateTodoItemCommand, int>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public CreateTodoItemCommandHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<int> Handle(CreateTodoItemCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = new TodoItem
|
||||
@@ -31,9 +26,9 @@ public class CreateTodoItemCommandHandler : IRequestHandler<CreateTodoItemComman
|
||||
|
||||
entity.AddDomainEvent(new TodoItemCreatedEvent(entity));
|
||||
|
||||
_context.TodoItems.Add(entity);
|
||||
context.TodoItems.Add(entity);
|
||||
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
await context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return entity.Id;
|
||||
}
|
||||
|
||||
@@ -9,27 +9,22 @@ namespace Hutopy.Application.TodoItems.Commands.DeleteTodoItem;
|
||||
[Authorize(Policy = Policies.CanDelete)]
|
||||
public record DeleteTodoItemCommand(int Id) : IRequest;
|
||||
|
||||
public class DeleteTodoItemCommandHandler : IRequestHandler<DeleteTodoItemCommand>
|
||||
public class DeleteTodoItemCommandHandler(
|
||||
IApplicationDbContext context)
|
||||
: IRequestHandler<DeleteTodoItemCommand>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public DeleteTodoItemCommandHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task Handle(DeleteTodoItemCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _context.TodoItems
|
||||
var entity = await context.TodoItems
|
||||
.FindAsync(new object[] { request.Id }, cancellationToken);
|
||||
|
||||
Guard.Against.NotFound(request.Id, entity);
|
||||
|
||||
_context.TodoItems.Remove(entity);
|
||||
context.TodoItems.Remove(entity);
|
||||
|
||||
entity.AddDomainEvent(new TodoItemDeletedEvent(entity));
|
||||
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
await context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,18 +11,13 @@ public record UpdateTodoItemCommand : IRequest
|
||||
public bool Done { get; init; }
|
||||
}
|
||||
|
||||
public class UpdateTodoItemCommandHandler : IRequestHandler<UpdateTodoItemCommand>
|
||||
public class UpdateTodoItemCommandHandler(
|
||||
IApplicationDbContext context)
|
||||
: IRequestHandler<UpdateTodoItemCommand>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public UpdateTodoItemCommandHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task Handle(UpdateTodoItemCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _context.TodoItems
|
||||
var entity = await context.TodoItems
|
||||
.FindAsync(new object[] { request.Id }, cancellationToken);
|
||||
|
||||
Guard.Against.NotFound(request.Id, entity);
|
||||
@@ -30,6 +25,6 @@ public class UpdateTodoItemCommandHandler : IRequestHandler<UpdateTodoItemComman
|
||||
entity.Title = request.Title;
|
||||
entity.Done = request.Done;
|
||||
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
await context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,18 +14,13 @@ public record UpdateTodoItemDetailCommand : IRequest
|
||||
public string? Note { get; init; }
|
||||
}
|
||||
|
||||
public class UpdateTodoItemDetailCommandHandler : IRequestHandler<UpdateTodoItemDetailCommand>
|
||||
public class UpdateTodoItemDetailCommandHandler(
|
||||
IApplicationDbContext context)
|
||||
: IRequestHandler<UpdateTodoItemDetailCommand>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public UpdateTodoItemDetailCommandHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task Handle(UpdateTodoItemDetailCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _context.TodoItems
|
||||
var entity = await context.TodoItems
|
||||
.FindAsync(new object[] { request.Id }, cancellationToken);
|
||||
|
||||
Guard.Against.NotFound(request.Id, entity);
|
||||
@@ -34,6 +29,6 @@ public class UpdateTodoItemDetailCommandHandler : IRequestHandler<UpdateTodoItem
|
||||
entity.Priority = request.Priority;
|
||||
entity.Note = request.Note;
|
||||
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
await context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,18 +3,13 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Hutopy.Application.TodoItems.EventHandlers;
|
||||
|
||||
public class TodoItemCompletedEventHandler : INotificationHandler<TodoItemCompletedEvent>
|
||||
public class TodoItemCompletedEventHandler(
|
||||
ILogger<TodoItemCompletedEventHandler> logger)
|
||||
: INotificationHandler<TodoItemCompletedEvent>
|
||||
{
|
||||
private readonly ILogger<TodoItemCompletedEventHandler> _logger;
|
||||
|
||||
public TodoItemCompletedEventHandler(ILogger<TodoItemCompletedEventHandler> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public Task Handle(TodoItemCompletedEvent notification, CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("Hutopy Domain Event: {DomainEvent}", notification.GetType().Name);
|
||||
logger.LogInformation("Hutopy Domain Event: {DomainEvent}", notification.GetType().Name);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -3,18 +3,13 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Hutopy.Application.TodoItems.EventHandlers;
|
||||
|
||||
public class TodoItemCreatedEventHandler : INotificationHandler<TodoItemCreatedEvent>
|
||||
public class TodoItemCreatedEventHandler(
|
||||
ILogger<TodoItemCreatedEventHandler> logger)
|
||||
: INotificationHandler<TodoItemCreatedEvent>
|
||||
{
|
||||
private readonly ILogger<TodoItemCreatedEventHandler> _logger;
|
||||
|
||||
public TodoItemCreatedEventHandler(ILogger<TodoItemCreatedEventHandler> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public Task Handle(TodoItemCreatedEvent notification, CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("Hutopy Domain Event: {DomainEvent}", notification.GetType().Name);
|
||||
logger.LogInformation("Hutopy Domain Event: {DomainEvent}", notification.GetType().Name);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -4,31 +4,25 @@ using Hutopy.Application.Common.Models;
|
||||
|
||||
namespace Hutopy.Application.TodoItems.Queries.GetTodoItemsWithPagination;
|
||||
|
||||
public record GetTodoItemsWithPaginationQuery : IRequest<PaginatedList<TodoItemBriefDto>>
|
||||
public abstract record GetTodoItemsWithPaginationQuery : IRequest<PaginatedList<TodoItemBriefDto>>
|
||||
{
|
||||
public int ListId { get; init; }
|
||||
public int PageNumber { get; init; } = 1;
|
||||
public int PageSize { get; init; } = 10;
|
||||
}
|
||||
|
||||
public class GetTodoItemsWithPaginationQueryHandler : IRequestHandler<GetTodoItemsWithPaginationQuery, PaginatedList<TodoItemBriefDto>>
|
||||
public class GetTodoItemsWithPaginationQueryHandler(
|
||||
IApplicationDbContext context,
|
||||
IMapper mapper)
|
||||
: IRequestHandler<GetTodoItemsWithPaginationQuery, PaginatedList<TodoItemBriefDto>>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public GetTodoItemsWithPaginationQueryHandler(IApplicationDbContext context, IMapper mapper)
|
||||
{
|
||||
_context = context;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public async Task<PaginatedList<TodoItemBriefDto>> Handle(GetTodoItemsWithPaginationQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
Console.WriteLine(request);
|
||||
return await _context.TodoItems
|
||||
return await context.TodoItems
|
||||
.Where(x => x.ListId == request.ListId)
|
||||
.OrderBy(x => x.Title)
|
||||
.ProjectTo<TodoItemBriefDto>(_mapper.ConfigurationProvider)
|
||||
.ProjectTo<TodoItemBriefDto>(mapper.ConfigurationProvider)
|
||||
.PaginatedListAsync(request.PageNumber, request.PageSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,24 +8,17 @@ public record CreateTodoListCommand : IRequest<int>
|
||||
public string? Title { get; init; }
|
||||
}
|
||||
|
||||
public class CreateTodoListCommandHandler : IRequestHandler<CreateTodoListCommand, int>
|
||||
public class CreateTodoListCommandHandler(
|
||||
IApplicationDbContext context)
|
||||
: IRequestHandler<CreateTodoListCommand, int>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public CreateTodoListCommandHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<int> Handle(CreateTodoListCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = new TodoList();
|
||||
var entity = new TodoList { Title = request.Title };
|
||||
|
||||
entity.Title = request.Title;
|
||||
context.TodoLists.Add(entity);
|
||||
|
||||
_context.TodoLists.Add(entity);
|
||||
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
await context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return entity.Id;
|
||||
}
|
||||
|
||||
@@ -4,25 +4,20 @@ namespace Hutopy.Application.TodoLists.Commands.DeleteTodoList;
|
||||
|
||||
public record DeleteTodoListCommand(int Id) : IRequest;
|
||||
|
||||
public class DeleteTodoListCommandHandler : IRequestHandler<DeleteTodoListCommand>
|
||||
public class DeleteTodoListCommandHandler(
|
||||
IApplicationDbContext context)
|
||||
: IRequestHandler<DeleteTodoListCommand>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public DeleteTodoListCommandHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task Handle(DeleteTodoListCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _context.TodoLists
|
||||
var entity = await context.TodoLists
|
||||
.Where(l => l.Id == request.Id)
|
||||
.SingleOrDefaultAsync(cancellationToken);
|
||||
|
||||
Guard.Against.NotFound(request.Id, entity);
|
||||
|
||||
_context.TodoLists.Remove(entity);
|
||||
context.TodoLists.Remove(entity);
|
||||
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
await context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,19 +8,14 @@ namespace Hutopy.Application.TodoLists.Commands.PurgeTodoLists;
|
||||
[Authorize(Policy = Policies.CanPurge)]
|
||||
public record PurgeTodoListsCommand : IRequest;
|
||||
|
||||
public class PurgeTodoListsCommandHandler : IRequestHandler<PurgeTodoListsCommand>
|
||||
public class PurgeTodoListsCommandHandler(
|
||||
IApplicationDbContext context)
|
||||
: IRequestHandler<PurgeTodoListsCommand>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public PurgeTodoListsCommandHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task Handle(PurgeTodoListsCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
_context.TodoLists.RemoveRange(_context.TodoLists);
|
||||
context.TodoLists.RemoveRange(context.TodoLists);
|
||||
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
await context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,25 +9,20 @@ public record UpdateTodoListCommand : IRequest
|
||||
public string? Title { get; init; }
|
||||
}
|
||||
|
||||
public class UpdateTodoListCommandHandler : IRequestHandler<UpdateTodoListCommand>
|
||||
public class UpdateTodoListCommandHandler(
|
||||
IApplicationDbContext context)
|
||||
: IRequestHandler<UpdateTodoListCommand>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public UpdateTodoListCommandHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task Handle(UpdateTodoListCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _context.TodoLists
|
||||
var entity = await context.TodoLists
|
||||
.FindAsync(new object[] { request.Id }, cancellationToken);
|
||||
|
||||
Guard.Against.NotFound(request.Id, entity);
|
||||
|
||||
entity.Title = request.Title;
|
||||
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
await context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ public class UpdateTodoListCommandValidator : AbstractValidator<UpdateTodoListCo
|
||||
.WithErrorCode("Unique");
|
||||
}
|
||||
|
||||
public async Task<bool> BeUniqueTitle(UpdateTodoListCommand model, string title, CancellationToken cancellationToken)
|
||||
private async Task<bool> BeUniqueTitle(UpdateTodoListCommand model, string title, CancellationToken cancellationToken)
|
||||
{
|
||||
return await _context.TodoLists
|
||||
.Where(l => l.Id != model.Id)
|
||||
|
||||
@@ -8,17 +8,11 @@ namespace Hutopy.Application.TodoLists.Queries.GetTodos;
|
||||
[Authorize]
|
||||
public record GetTodosQuery : IRequest<TodosVm>;
|
||||
|
||||
public class GetTodosQueryHandler : IRequestHandler<GetTodosQuery, TodosVm>
|
||||
public class GetTodosQueryHandler(
|
||||
IApplicationDbContext context,
|
||||
IMapper mapper)
|
||||
: IRequestHandler<GetTodosQuery, TodosVm>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public GetTodosQueryHandler(IApplicationDbContext context, IMapper mapper)
|
||||
{
|
||||
_context = context;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public async Task<TodosVm> Handle(GetTodosQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
return new TodosVm
|
||||
@@ -28,9 +22,9 @@ public class GetTodosQueryHandler : IRequestHandler<GetTodosQuery, TodosVm>
|
||||
.Select(p => new LookupDto { Id = (int)p, Title = p.ToString() })
|
||||
.ToList(),
|
||||
|
||||
Lists = await _context.TodoLists
|
||||
Lists = await context.TodoLists
|
||||
.AsNoTracking()
|
||||
.ProjectTo<TodoListDto>(_mapper.ConfigurationProvider)
|
||||
.ProjectTo<TodoListDto>(mapper.ConfigurationProvider)
|
||||
.OrderBy(t => t.Title)
|
||||
.ToListAsync(cancellationToken)
|
||||
};
|
||||
|
||||
@@ -4,18 +4,13 @@ namespace Hutopy.Application.TodoLists.Queries.GetTodos;
|
||||
|
||||
public class TodoListDto
|
||||
{
|
||||
public TodoListDto()
|
||||
{
|
||||
Items = Array.Empty<TodoItemDto>();
|
||||
}
|
||||
|
||||
public int Id { get; init; }
|
||||
|
||||
public string? Title { get; init; }
|
||||
|
||||
public string? Colour { get; init; }
|
||||
|
||||
public IReadOnlyCollection<TodoItemDto> Items { get; init; }
|
||||
public IReadOnlyCollection<TodoItemDto> Items { get; init; } = Array.Empty<TodoItemDto>();
|
||||
|
||||
private class Mapping : Profile
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user