Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻️ Application layer refactoring #878

Merged
merged 6 commits into from
Jun 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Application/Application.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Ardalis.GuardClauses" Version="4.0.1" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.5.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0-preview.5.23280.1" />
Expand Down
13 changes: 6 additions & 7 deletions src/Application/Common/Behaviours/AuthorizationBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,19 @@
using CleanArchitecture.Application.Common.Exceptions;
using CleanArchitecture.Application.Common.Interfaces;
using CleanArchitecture.Application.Common.Security;
using MediatR;

namespace CleanArchitecture.Application.Common.Behaviours;

public class AuthorizationBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : notnull
{
private readonly ICurrentUserService _currentUserService;
private readonly IUser _user;
private readonly IIdentityService _identityService;

public AuthorizationBehaviour(
ICurrentUserService currentUserService,
IUser user,
IIdentityService identityService)
{
_currentUserService = currentUserService;
_user = user;
_identityService = identityService;
}

Expand All @@ -26,7 +25,7 @@ public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TRe
if (authorizeAttributes.Any())
{
// Must be authenticated user
if (_currentUserService.UserId == null)
if (_user.Id == null)
{
throw new UnauthorizedAccessException();
}
Expand All @@ -42,7 +41,7 @@ public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TRe
{
foreach (var role in roles)
{
var isInRole = await _identityService.IsInRoleAsync(_currentUserService.UserId, role.Trim());
var isInRole = await _identityService.IsInRoleAsync(_user.Id, role.Trim());
if (isInRole)
{
authorized = true;
Expand All @@ -64,7 +63,7 @@ public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TRe
{
foreach (var policy in authorizeAttributesWithPolicies.Select(a => a.Policy))
{
var authorized = await _identityService.AuthorizeAsync(_currentUserService.UserId, policy);
var authorized = await _identityService.AuthorizeAsync(_user.Id, policy);

if (!authorized)
{
Expand Down
8 changes: 4 additions & 4 deletions src/Application/Common/Behaviours/LoggingBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ namespace CleanArchitecture.Application.Common.Behaviours;
public class LoggingBehaviour<TRequest> : IRequestPreProcessor<TRequest> where TRequest : notnull
{
private readonly ILogger _logger;
private readonly ICurrentUserService _currentUserService;
private readonly IUser _user;
private readonly IIdentityService _identityService;

public LoggingBehaviour(ILogger<TRequest> logger, ICurrentUserService currentUserService, IIdentityService identityService)
public LoggingBehaviour(ILogger<TRequest> logger, IUser user, IIdentityService identityService)
{
_logger = logger;
_currentUserService = currentUserService;
_user = user;
_identityService = identityService;
}

public async Task Process(TRequest request, CancellationToken cancellationToken)
{
var requestName = typeof(TRequest).Name;
var userId = _currentUserService.UserId ?? string.Empty;
var userId = _user.Id ?? string.Empty;
string? userName = string.Empty;

if (!string.IsNullOrEmpty(userId))
Expand Down
9 changes: 4 additions & 5 deletions src/Application/Common/Behaviours/PerformanceBehaviour.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Diagnostics;
using CleanArchitecture.Application.Common.Interfaces;
using MediatR;
using Microsoft.Extensions.Logging;

namespace CleanArchitecture.Application.Common.Behaviours;
Expand All @@ -9,18 +8,18 @@ public class PerformanceBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequ
{
private readonly Stopwatch _timer;
private readonly ILogger<TRequest> _logger;
private readonly ICurrentUserService _currentUserService;
private readonly IUser _user;
private readonly IIdentityService _identityService;

public PerformanceBehaviour(
ILogger<TRequest> logger,
ICurrentUserService currentUserService,
IUser user,
IIdentityService identityService)
{
_timer = new Stopwatch();

_logger = logger;
_currentUserService = currentUserService;
_user = user;
_identityService = identityService;
}

Expand All @@ -37,7 +36,7 @@ public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TRe
if (elapsedMilliseconds > 500)
{
var requestName = typeof(TRequest).Name;
var userId = _currentUserService.UserId ?? string.Empty;
var userId = _user.Id ?? string.Empty;
var userName = string.Empty;

if (!string.IsNullOrEmpty(userId))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using MediatR;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging;

namespace CleanArchitecture.Application.Common.Behaviours;

Expand Down
4 changes: 1 addition & 3 deletions src/Application/Common/Behaviours/ValidationBehaviour.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using FluentValidation;
using MediatR;
using ValidationException = CleanArchitecture.Application.Common.Exceptions.ValidationException;
using ValidationException = CleanArchitecture.Application.Common.Exceptions.ValidationException;

namespace CleanArchitecture.Application.Common.Behaviours;

Expand Down
24 changes: 0 additions & 24 deletions src/Application/Common/Exceptions/NotFoundException.cs

This file was deleted.

1 change: 0 additions & 1 deletion src/Application/Common/Interfaces/IApplicationDbContext.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using CleanArchitecture.Domain.Entities;
using Microsoft.EntityFrameworkCore;

namespace CleanArchitecture.Application.Common.Interfaces;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace CleanArchitecture.Application.Common.Interfaces;

public interface ICurrentUserService
public interface IUser
{
string? UserId { get; }
string? Id { get; }
}
1 change: 0 additions & 1 deletion src/Application/Common/Mappings/MappingExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using CleanArchitecture.Application.Common.Models;
using Microsoft.EntityFrameworkCore;

namespace CleanArchitecture.Application.Common.Mappings;

Expand Down
4 changes: 1 addition & 3 deletions src/Application/Common/Models/PaginatedList.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using Microsoft.EntityFrameworkCore;

namespace CleanArchitecture.Application.Common.Models;
namespace CleanArchitecture.Application.Common.Models;

public class PaginatedList<T>
{
Expand Down
5 changes: 2 additions & 3 deletions src/Application/ConfigureServices.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System.Reflection;
using CleanArchitecture.Application.Common.Behaviours;
using FluentValidation;
using MediatR;

namespace Microsoft.Extensions.DependencyInjection;

Expand All @@ -10,14 +8,15 @@ public static class ConfigureServices
public static IServiceCollection AddApplicationServices(this IServiceCollection services)
{
services.AddAutoMapper(Assembly.GetExecutingAssembly());

services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly());

services.AddMediatR(cfg => {
cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly());
cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(UnhandledExceptionBehaviour<,>));
cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(AuthorizationBehaviour<,>));
cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(ValidationBehaviour<,>));
cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(PerformanceBehaviour<,>));

});

return services;
Expand Down
8 changes: 6 additions & 2 deletions src/Application/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
global using AutoMapper;
global using AutoMapper.QueryableExtensions;
global using Ardalis.GuardClauses;
global using AutoMapper;
global using AutoMapper.QueryableExtensions;
global using Microsoft.EntityFrameworkCore;
global using FluentValidation;
global using MediatR;
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using CleanArchitecture.Application.Common.Interfaces;
using CleanArchitecture.Domain.Entities;
using CleanArchitecture.Domain.Events;
using MediatR;

namespace CleanArchitecture.Application.TodoItems.Commands.CreateTodoItem;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using FluentValidation;

namespace CleanArchitecture.Application.TodoItems.Commands.CreateTodoItem;
namespace CleanArchitecture.Application.TodoItems.Commands.CreateTodoItem;

public class CreateTodoItemCommandValidator : AbstractValidator<CreateTodoItemCommand>
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
using CleanArchitecture.Application.Common.Exceptions;
using CleanArchitecture.Application.Common.Interfaces;
using CleanArchitecture.Domain.Entities;
using CleanArchitecture.Application.Common.Interfaces;
using CleanArchitecture.Domain.Events;
using MediatR;

namespace CleanArchitecture.Application.TodoItems.Commands.DeleteTodoItem;

Expand All @@ -22,10 +19,7 @@ public async Task Handle(DeleteTodoItemCommand request, CancellationToken cancel
var entity = await _context.TodoItems
.FindAsync(new object[] { request.Id }, cancellationToken);

if (entity == null)
{
throw new NotFoundException(nameof(TodoItem), request.Id);
}
Guard.Against.NotFound(request.Id, entity);

_context.TodoItems.Remove(entity);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using CleanArchitecture.Application.Common.Exceptions;
using CleanArchitecture.Application.Common.Interfaces;
using CleanArchitecture.Domain.Entities;
using MediatR;
using CleanArchitecture.Application.Common.Interfaces;

namespace CleanArchitecture.Application.TodoItems.Commands.UpdateTodoItem;

Expand All @@ -28,10 +25,7 @@ public async Task Handle(UpdateTodoItemCommand request, CancellationToken cancel
var entity = await _context.TodoItems
.FindAsync(new object[] { request.Id }, cancellationToken);

if (entity == null)
{
throw new NotFoundException(nameof(TodoItem), request.Id);
}
Guard.Against.NotFound(request.Id, entity);

entity.Title = request.Title;
entity.Done = request.Done;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using FluentValidation;

namespace CleanArchitecture.Application.TodoItems.Commands.UpdateTodoItem;
namespace CleanArchitecture.Application.TodoItems.Commands.UpdateTodoItem;

public class UpdateTodoItemCommandValidator : AbstractValidator<UpdateTodoItemCommand>
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
using CleanArchitecture.Application.Common.Exceptions;
using CleanArchitecture.Application.Common.Interfaces;
using CleanArchitecture.Domain.Entities;
using CleanArchitecture.Application.Common.Interfaces;
using CleanArchitecture.Domain.Enums;
using MediatR;

namespace CleanArchitecture.Application.TodoItems.Commands.UpdateTodoItemDetail;

Expand Down Expand Up @@ -31,10 +28,7 @@ public async Task Handle(UpdateTodoItemDetailCommand request, CancellationToken
var entity = await _context.TodoItems
.FindAsync(new object[] { request.Id }, cancellationToken);

if (entity == null)
{
throw new NotFoundException(nameof(TodoItem), request.Id);
}
Guard.Against.NotFound(request.Id, entity);

entity.ListId = request.ListId;
entity.Priority = request.Priority;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using CleanArchitecture.Domain.Events;
using MediatR;
using Microsoft.Extensions.Logging;

namespace CleanArchitecture.Application.TodoItems.EventHandlers;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using CleanArchitecture.Domain.Events;
using MediatR;
using Microsoft.Extensions.Logging;

namespace CleanArchitecture.Application.TodoItems.EventHandlers;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using CleanArchitecture.Application.Common.Interfaces;
using CleanArchitecture.Application.Common.Mappings;
using CleanArchitecture.Application.Common.Models;
using MediatR;

namespace CleanArchitecture.Application.TodoItems.Queries.GetTodoItemsWithPagination;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using FluentValidation;

namespace CleanArchitecture.Application.TodoItems.Queries.GetTodoItemsWithPagination;
namespace CleanArchitecture.Application.TodoItems.Queries.GetTodoItemsWithPagination;

public class GetTodoItemsWithPaginationQueryValidator : AbstractValidator<GetTodoItemsWithPaginationQuery>
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using CleanArchitecture.Application.Common.Interfaces;
using CleanArchitecture.Domain.Entities;
using MediatR;

namespace CleanArchitecture.Application.TodoLists.Commands.CreateTodoList;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using CleanArchitecture.Application.Common.Interfaces;
using FluentValidation;
using Microsoft.EntityFrameworkCore;

namespace CleanArchitecture.Application.TodoLists.Commands.CreateTodoList;

Expand All @@ -13,9 +11,11 @@ public CreateTodoListCommandValidator(IApplicationDbContext context)
_context = context;

RuleFor(v => v.Title)
.NotEmpty().WithMessage("Title is required.")
.MaximumLength(200).WithMessage("Title must not exceed 200 characters.")
.MustAsync(BeUniqueTitle).WithMessage("The specified title already exists.");
.NotEmpty()
.MaximumLength(200)
.MustAsync(BeUniqueTitle)
.WithMessage("'{PropertyName}' must be unique.")
.WithErrorCode("Unique");
}

public async Task<bool> BeUniqueTitle(string title, CancellationToken cancellationToken)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
using CleanArchitecture.Application.Common.Exceptions;
using CleanArchitecture.Application.Common.Interfaces;
using CleanArchitecture.Domain.Entities;
using MediatR;
using Microsoft.EntityFrameworkCore;
using CleanArchitecture.Application.Common.Interfaces;

namespace CleanArchitecture.Application.TodoLists.Commands.DeleteTodoList;

Expand All @@ -23,10 +19,7 @@ public async Task Handle(DeleteTodoListCommand request, CancellationToken cancel
.Where(l => l.Id == request.Id)
.SingleOrDefaultAsync(cancellationToken);

if (entity == null)
{
throw new NotFoundException(nameof(TodoList), request.Id);
}
Guard.Against.NotFound(request.Id, entity);

_context.TodoLists.Remove(entity);

Expand Down
Loading