From f645b2cc8faef1ea24878d2c80b67f6e41093df2 Mon Sep 17 00:00:00 2001 From: Alexander Konietzko Date: Mon, 13 Mar 2023 20:34:40 +0100 Subject: [PATCH] Add gRPC and fix some warnings --- .../CleanArchitecture.Api.csproj | 1 + .../Controllers/ApiController.cs | 2 +- .../Controllers/UserController.cs | 6 +- CleanArchitecture.Api/Program.cs | 3 + ...CleanArchitecture.Application.Tests.csproj | 1 - .../Queries/Users/GetAllUsersTestFixture.cs | 4 +- .../Queries/Users/GetUserByIdTestFixture.cs | 4 +- .../Users/GetAllUsersQueryHandlerTests.cs | 4 +- .../Users/GetUserByIdQueryHandlerTests.cs | 6 +- .../Extensions/ServiceCollectionExtension.cs | 1 - .../Interfaces/IUserService.cs | 2 +- .../Queries/Users/GetAll/GetAllUsersQuery.cs | 3 +- .../Users/GetAll/GetAllUsersQueryHandler.cs | 1 - .../Users/GetUserById/GetUserByIdQuery.cs | 3 +- .../GetUserById/GetUserByIdQueryHandler.cs | 5 +- .../Services/UserService.cs | 4 +- .../CleanArchitecture.Domain.Tests.csproj | 1 - .../CreateUserCommandHandlerTests.cs | 1 + .../CreateUserCommandTestFixture.cs | 1 + .../CreateUserCommandValidationTests.cs | 1 + .../DeleteUserCommandHandlerTests.cs | 1 + .../DeleteUserCommandTestFixture.cs | 1 + .../DeleteUserCommandValidationTests.cs | 1 + .../UpdateUserCommandHandlerTests.cs | 4 +- .../UpdateUserCommandTestFixture.cs | 1 + .../UpdateUserCommandValidationTests.cs | 1 + .../CommandHandlerFixtureBase.cs | 7 +- .../ValidationTestBase.cs | 4 +- .../Users/CreateUser/CreateUserCommand.cs | 2 +- .../Users/DeleteUser/DeleteUserCommand.cs | 2 +- ...anArchitecture.Infrastructure.Tests.csproj | 1 - .../DomainNotificationHandlerTests.cs | 2 +- .../DomainNotificationTests.cs | 3 +- .../InMemoryBusTests.cs | 3 + .../UnitOfWorkTests.cs | 9 ++- .../Repositories/BaseRepository.cs | 26 +++---- .../Repositories/UserRepository.cs | 2 +- .../UnitOfWork.cs | 5 +- .../CleanArchitecture.IntegrationTests.csproj | 1 - .../Controller/UserControllerTests.cs | 12 ++- ...ctionalTestsServiceCollectionExtensions.cs | 9 ++- .../Extensions/HttpExtensions.cs | 8 +- .../Fixtures/TestFixtureBase.cs | 5 +- .../Fixtures/UserTestFixture.cs | 4 +- .../CleanArchitectureWebApplicationFactory.cs | 3 +- .../CleanArchitecture.Proto.csproj | 24 ++++++ CleanArchitecture.Proto/Users/Models.proto | 11 +++ CleanArchitecture.Proto/Users/UsersApi.proto | 17 +++++ .../CleanArchitecture.gRPC.Tests.csproj | 31 ++++++++ .../Fixtures/UserTestsFixture.cs | 36 +++++++++ .../Users/GetUsersByIdsTests.cs | 74 +++++++++++++++++++ .../CleanArchitecture.gRPC.csproj | 17 +++++ .../UsersApiImplementation.cs | 54 ++++++++++++++ CleanArchitecture.sln | 18 +++++ Todo.txt | 3 +- 55 files changed, 391 insertions(+), 65 deletions(-) create mode 100644 CleanArchitecture.Proto/CleanArchitecture.Proto.csproj create mode 100644 CleanArchitecture.Proto/Users/Models.proto create mode 100644 CleanArchitecture.Proto/Users/UsersApi.proto create mode 100644 CleanArchitecture.gRPC.Tests/CleanArchitecture.gRPC.Tests.csproj create mode 100644 CleanArchitecture.gRPC.Tests/Fixtures/UserTestsFixture.cs create mode 100644 CleanArchitecture.gRPC.Tests/Users/GetUsersByIdsTests.cs create mode 100644 CleanArchitecture.gRPC/CleanArchitecture.gRPC.csproj create mode 100644 CleanArchitecture.gRPC/UsersApiImplementation.cs diff --git a/CleanArchitecture.Api/CleanArchitecture.Api.csproj b/CleanArchitecture.Api/CleanArchitecture.Api.csproj index 749f190..6d798e4 100644 --- a/CleanArchitecture.Api/CleanArchitecture.Api.csproj +++ b/CleanArchitecture.Api/CleanArchitecture.Api.csproj @@ -24,6 +24,7 @@ + diff --git a/CleanArchitecture.Api/Controllers/ApiController.cs b/CleanArchitecture.Api/Controllers/ApiController.cs index d30048e..ddb8cd0 100644 --- a/CleanArchitecture.Api/Controllers/ApiController.cs +++ b/CleanArchitecture.Api/Controllers/ApiController.cs @@ -56,7 +56,7 @@ public class ApiController : ControllerBase return GetErrorStatusCode(); } - protected HttpStatusCode GetErrorStatusCode() + private HttpStatusCode GetErrorStatusCode() { if (_notifications.GetNotifications().Any(n => n.Code == ErrorCodes.ObjectNotFound)) { diff --git a/CleanArchitecture.Api/Controllers/UserController.cs b/CleanArchitecture.Api/Controllers/UserController.cs index a31a158..5d6cfc6 100644 --- a/CleanArchitecture.Api/Controllers/UserController.cs +++ b/CleanArchitecture.Api/Controllers/UserController.cs @@ -29,9 +29,11 @@ public class UserController : ApiController } [HttpGet("{id}")] - public async Task GetUserByIdAsync([FromRoute] Guid id) + public async Task GetUserByIdAsync( + [FromRoute] Guid id, + [FromQuery] bool isDeleted = false) { - var user = await _userService.GetUserByUserIdAsync(id); + var user = await _userService.GetUserByUserIdAsync(id, isDeleted); return Response(user); } diff --git a/CleanArchitecture.Api/Program.cs b/CleanArchitecture.Api/Program.cs index db6a81b..4aee2bc 100644 --- a/CleanArchitecture.Api/Program.cs +++ b/CleanArchitecture.Api/Program.cs @@ -1,5 +1,6 @@ using CleanArchitecture.Application.Extensions; using CleanArchitecture.Domain.Extensions; +using CleanArchitecture.gRPC; using CleanArchitecture.Infrastructure.Database; using CleanArchitecture.Infrastructure.Extensions; using Microsoft.AspNetCore.Builder; @@ -10,6 +11,7 @@ using Microsoft.Extensions.DependencyInjection; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); +builder.Services.AddGrpc(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); @@ -43,6 +45,7 @@ app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); +app.MapGrpcService(); using (IServiceScope scope = app.Services.CreateScope()) { diff --git a/CleanArchitecture.Application.Tests/CleanArchitecture.Application.Tests.csproj b/CleanArchitecture.Application.Tests/CleanArchitecture.Application.Tests.csproj index 129ebce..f93ebb1 100644 --- a/CleanArchitecture.Application.Tests/CleanArchitecture.Application.Tests.csproj +++ b/CleanArchitecture.Application.Tests/CleanArchitecture.Application.Tests.csproj @@ -2,7 +2,6 @@ net7.0 - enable enable false diff --git a/CleanArchitecture.Application.Tests/Fixtures/Queries/Users/GetAllUsersTestFixture.cs b/CleanArchitecture.Application.Tests/Fixtures/Queries/Users/GetAllUsersTestFixture.cs index ef02fbf..3357845 100644 --- a/CleanArchitecture.Application.Tests/Fixtures/Queries/Users/GetAllUsersTestFixture.cs +++ b/CleanArchitecture.Application.Tests/Fixtures/Queries/Users/GetAllUsersTestFixture.cs @@ -1,3 +1,5 @@ +using System; +using System.Linq; using CleanArchitecture.Application.Queries.Users.GetAll; using CleanArchitecture.Domain.Entities; using CleanArchitecture.Domain.Interfaces.Repositories; @@ -8,7 +10,7 @@ namespace CleanArchitecture.Application.Tests.Fixtures.Queries.Users; public sealed class GetAllUsersTestFixture : QueryHandlerBaseFixture { - public Mock UserRepository { get; } + private Mock UserRepository { get; } public GetAllUsersQueryHandler Handler { get; } public Guid ExistingUserId { get; } = Guid.NewGuid(); diff --git a/CleanArchitecture.Application.Tests/Fixtures/Queries/Users/GetUserByIdTestFixture.cs b/CleanArchitecture.Application.Tests/Fixtures/Queries/Users/GetUserByIdTestFixture.cs index 0671991..d50699f 100644 --- a/CleanArchitecture.Application.Tests/Fixtures/Queries/Users/GetUserByIdTestFixture.cs +++ b/CleanArchitecture.Application.Tests/Fixtures/Queries/Users/GetUserByIdTestFixture.cs @@ -1,3 +1,5 @@ +using System; +using System.Linq; using CleanArchitecture.Application.Queries.Users.GetUserById; using CleanArchitecture.Domain.Entities; using CleanArchitecture.Domain.Interfaces.Repositories; @@ -8,7 +10,7 @@ namespace CleanArchitecture.Application.Tests.Fixtures.Queries.Users; public sealed class GetUserByIdTestFixture : QueryHandlerBaseFixture { - public Mock UserRepository { get; } + private Mock UserRepository { get; } public GetUserByIdQueryHandler Handler { get; } public Guid ExistingUserId { get; } = Guid.NewGuid(); diff --git a/CleanArchitecture.Application.Tests/Queries/Users/GetAllUsersQueryHandlerTests.cs b/CleanArchitecture.Application.Tests/Queries/Users/GetAllUsersQueryHandlerTests.cs index a625aa0..44af10e 100644 --- a/CleanArchitecture.Application.Tests/Queries/Users/GetAllUsersQueryHandlerTests.cs +++ b/CleanArchitecture.Application.Tests/Queries/Users/GetAllUsersQueryHandlerTests.cs @@ -1,3 +1,5 @@ +using System.Linq; +using System.Threading.Tasks; using CleanArchitecture.Application.Tests.Fixtures.Queries.Users; using FluentAssertions; using Xunit; @@ -18,7 +20,7 @@ public sealed class GetAllUsersQueryHandlerTests default); _fixture.VerifyNoDomainNotification(); - + result.Should().NotBeNull(); result.Should().ContainSingle(); result.FirstOrDefault()!.Id.Should().Be(_fixture.ExistingUserId); diff --git a/CleanArchitecture.Application.Tests/Queries/Users/GetUserByIdQueryHandlerTests.cs b/CleanArchitecture.Application.Tests/Queries/Users/GetUserByIdQueryHandlerTests.cs index f24ece9..b4fa2bd 100644 --- a/CleanArchitecture.Application.Tests/Queries/Users/GetUserByIdQueryHandlerTests.cs +++ b/CleanArchitecture.Application.Tests/Queries/Users/GetUserByIdQueryHandlerTests.cs @@ -1,3 +1,5 @@ +using System; +using System.Threading.Tasks; using CleanArchitecture.Application.Queries.Users.GetUserById; using CleanArchitecture.Application.Tests.Fixtures.Queries.Users; using CleanArchitecture.Domain.Errors; @@ -16,7 +18,7 @@ public sealed class GetUserByIdQueryHandlerTests _fixture.SetupUserAsync(); var result = await _fixture.Handler.Handle( - new(_fixture.ExistingUserId), + new(_fixture.ExistingUserId, false), default); _fixture.VerifyNoDomainNotification(); @@ -30,7 +32,7 @@ public sealed class GetUserByIdQueryHandlerTests { _fixture.SetupUserAsync(); - var request = new GetUserByIdQuery(Guid.NewGuid()); + var request = new GetUserByIdQuery(Guid.NewGuid(), false); var result = await _fixture.Handler.Handle( request, default); diff --git a/CleanArchitecture.Application/Extensions/ServiceCollectionExtension.cs b/CleanArchitecture.Application/Extensions/ServiceCollectionExtension.cs index 752e40e..beaec9f 100644 --- a/CleanArchitecture.Application/Extensions/ServiceCollectionExtension.cs +++ b/CleanArchitecture.Application/Extensions/ServiceCollectionExtension.cs @@ -3,7 +3,6 @@ using CleanArchitecture.Application.Interfaces; using CleanArchitecture.Application.Queries.Users.GetAll; using CleanArchitecture.Application.Queries.Users.GetUserById; using CleanArchitecture.Application.Services; -using CleanArchitecture.Application.ViewModels; using CleanArchitecture.Application.ViewModels.Users; using MediatR; using Microsoft.Extensions.DependencyInjection; diff --git a/CleanArchitecture.Application/Interfaces/IUserService.cs b/CleanArchitecture.Application/Interfaces/IUserService.cs index 650a50f..5f65254 100644 --- a/CleanArchitecture.Application/Interfaces/IUserService.cs +++ b/CleanArchitecture.Application/Interfaces/IUserService.cs @@ -7,7 +7,7 @@ namespace CleanArchitecture.Application.Interfaces; public interface IUserService { - public Task GetUserByUserIdAsync(Guid userId); + public Task GetUserByUserIdAsync(Guid userId, bool isDeleted); public Task> GetAllUsersAsync(); public Task CreateUserAsync(CreateUserViewModel user); public Task UpdateUserAsync(UpdateUserViewModel user); diff --git a/CleanArchitecture.Application/Queries/Users/GetAll/GetAllUsersQuery.cs b/CleanArchitecture.Application/Queries/Users/GetAll/GetAllUsersQuery.cs index 76e942c..40e8571 100644 --- a/CleanArchitecture.Application/Queries/Users/GetAll/GetAllUsersQuery.cs +++ b/CleanArchitecture.Application/Queries/Users/GetAll/GetAllUsersQuery.cs @@ -1,8 +1,7 @@ using System.Collections.Generic; -using CleanArchitecture.Application.ViewModels; using CleanArchitecture.Application.ViewModels.Users; using MediatR; namespace CleanArchitecture.Application.Queries.Users.GetAll; -public sealed record GetAllUsersQuery() : IRequest>; +public sealed record GetAllUsersQuery : IRequest>; diff --git a/CleanArchitecture.Application/Queries/Users/GetAll/GetAllUsersQueryHandler.cs b/CleanArchitecture.Application/Queries/Users/GetAll/GetAllUsersQueryHandler.cs index bcb4aad..c43bad2 100644 --- a/CleanArchitecture.Application/Queries/Users/GetAll/GetAllUsersQueryHandler.cs +++ b/CleanArchitecture.Application/Queries/Users/GetAll/GetAllUsersQueryHandler.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using CleanArchitecture.Application.ViewModels; using CleanArchitecture.Application.ViewModels.Users; using CleanArchitecture.Domain.Interfaces.Repositories; using MediatR; diff --git a/CleanArchitecture.Application/Queries/Users/GetUserById/GetUserByIdQuery.cs b/CleanArchitecture.Application/Queries/Users/GetUserById/GetUserByIdQuery.cs index 115a31a..e394336 100644 --- a/CleanArchitecture.Application/Queries/Users/GetUserById/GetUserByIdQuery.cs +++ b/CleanArchitecture.Application/Queries/Users/GetUserById/GetUserByIdQuery.cs @@ -1,8 +1,7 @@ using System; -using CleanArchitecture.Application.ViewModels; using CleanArchitecture.Application.ViewModels.Users; using MediatR; namespace CleanArchitecture.Application.Queries.Users.GetUserById; -public sealed record GetUserByIdQuery(Guid UserId) : IRequest; +public sealed record GetUserByIdQuery(Guid UserId, bool IsDeleted) : IRequest; diff --git a/CleanArchitecture.Application/Queries/Users/GetUserById/GetUserByIdQueryHandler.cs b/CleanArchitecture.Application/Queries/Users/GetUserById/GetUserByIdQueryHandler.cs index 1109d00..2c166a8 100644 --- a/CleanArchitecture.Application/Queries/Users/GetUserById/GetUserByIdQueryHandler.cs +++ b/CleanArchitecture.Application/Queries/Users/GetUserById/GetUserByIdQueryHandler.cs @@ -1,7 +1,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using CleanArchitecture.Application.ViewModels; using CleanArchitecture.Application.ViewModels.Users; using CleanArchitecture.Domain.Errors; using CleanArchitecture.Domain.Interfaces; @@ -27,7 +26,9 @@ public sealed class GetUserByIdQueryHandler : { var user = _userRepository .GetAllNoTracking() - .FirstOrDefault(x => x.Id == request.UserId && !x.Deleted); + .FirstOrDefault(x => + x.Id == request.UserId && + x.Deleted == request.IsDeleted); if (user == null) { diff --git a/CleanArchitecture.Application/Services/UserService.cs b/CleanArchitecture.Application/Services/UserService.cs index bd99d42..dd91d4f 100644 --- a/CleanArchitecture.Application/Services/UserService.cs +++ b/CleanArchitecture.Application/Services/UserService.cs @@ -21,9 +21,9 @@ public sealed class UserService : IUserService _bus = bus; } - public async Task GetUserByUserIdAsync(Guid userId) + public async Task GetUserByUserIdAsync(Guid userId, bool isDeleted) { - return await _bus.QueryAsync(new GetUserByIdQuery(userId)); + return await _bus.QueryAsync(new GetUserByIdQuery(userId, isDeleted)); } public async Task> GetAllUsersAsync() diff --git a/CleanArchitecture.Domain.Tests/CleanArchitecture.Domain.Tests.csproj b/CleanArchitecture.Domain.Tests/CleanArchitecture.Domain.Tests.csproj index 7ae8e02..3745ee4 100644 --- a/CleanArchitecture.Domain.Tests/CleanArchitecture.Domain.Tests.csproj +++ b/CleanArchitecture.Domain.Tests/CleanArchitecture.Domain.Tests.csproj @@ -2,7 +2,6 @@ net7.0 - enable enable false diff --git a/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandHandlerTests.cs b/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandHandlerTests.cs index 6cf2b53..7d5109f 100644 --- a/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandHandlerTests.cs +++ b/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandHandlerTests.cs @@ -1,3 +1,4 @@ +using System; using CleanArchitecture.Domain.Commands.Users.CreateUser; using CleanArchitecture.Domain.Errors; using CleanArchitecture.Domain.Events.User; diff --git a/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandTestFixture.cs b/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandTestFixture.cs index 50a82da..2f30515 100644 --- a/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandTestFixture.cs +++ b/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandTestFixture.cs @@ -1,3 +1,4 @@ +using System; using CleanArchitecture.Domain.Commands.Users.CreateUser; using CleanArchitecture.Domain.Interfaces.Repositories; using Moq; diff --git a/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandValidationTests.cs b/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandValidationTests.cs index 60fd654..a6c54e4 100644 --- a/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandValidationTests.cs +++ b/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandValidationTests.cs @@ -1,3 +1,4 @@ +using System; using CleanArchitecture.Domain.Commands.Users.CreateUser; using CleanArchitecture.Domain.Errors; using Xunit; diff --git a/CleanArchitecture.Domain.Tests/CommandHandler/User/DeleteUser/DeleteUserCommandHandlerTests.cs b/CleanArchitecture.Domain.Tests/CommandHandler/User/DeleteUser/DeleteUserCommandHandlerTests.cs index ef70639..dc23bd6 100644 --- a/CleanArchitecture.Domain.Tests/CommandHandler/User/DeleteUser/DeleteUserCommandHandlerTests.cs +++ b/CleanArchitecture.Domain.Tests/CommandHandler/User/DeleteUser/DeleteUserCommandHandlerTests.cs @@ -1,3 +1,4 @@ +using System; using CleanArchitecture.Domain.Commands.Users.DeleteUser; using CleanArchitecture.Domain.Errors; using CleanArchitecture.Domain.Events.User; diff --git a/CleanArchitecture.Domain.Tests/CommandHandler/User/DeleteUser/DeleteUserCommandTestFixture.cs b/CleanArchitecture.Domain.Tests/CommandHandler/User/DeleteUser/DeleteUserCommandTestFixture.cs index 9da0eee..19f7761 100644 --- a/CleanArchitecture.Domain.Tests/CommandHandler/User/DeleteUser/DeleteUserCommandTestFixture.cs +++ b/CleanArchitecture.Domain.Tests/CommandHandler/User/DeleteUser/DeleteUserCommandTestFixture.cs @@ -1,3 +1,4 @@ +using System; using CleanArchitecture.Domain.Commands.Users.DeleteUser; using CleanArchitecture.Domain.Interfaces.Repositories; using Moq; diff --git a/CleanArchitecture.Domain.Tests/CommandHandler/User/DeleteUser/DeleteUserCommandValidationTests.cs b/CleanArchitecture.Domain.Tests/CommandHandler/User/DeleteUser/DeleteUserCommandValidationTests.cs index 2c70984..50106e5 100644 --- a/CleanArchitecture.Domain.Tests/CommandHandler/User/DeleteUser/DeleteUserCommandValidationTests.cs +++ b/CleanArchitecture.Domain.Tests/CommandHandler/User/DeleteUser/DeleteUserCommandValidationTests.cs @@ -1,3 +1,4 @@ +using System; using CleanArchitecture.Domain.Commands.Users.DeleteUser; using CleanArchitecture.Domain.Errors; using Xunit; diff --git a/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandHandlerTests.cs b/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandHandlerTests.cs index 182f9ed..bdd53e6 100644 --- a/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandHandlerTests.cs +++ b/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandHandlerTests.cs @@ -1,3 +1,5 @@ +using System; +using System.Threading.Tasks; using CleanArchitecture.Domain.Commands.Users.UpdateUser; using CleanArchitecture.Domain.Errors; using CleanArchitecture.Domain.Events.User; @@ -31,7 +33,7 @@ public sealed class UpdateUserCommandHandlerTests [Fact] public async Task Should_Not_Update_Non_Existing_User() { - var user = _fixture.SetupUser(); + _fixture.SetupUser(); var command = new UpdateUserCommand( Guid.NewGuid(), diff --git a/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandTestFixture.cs b/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandTestFixture.cs index d3dd415..1b63128 100644 --- a/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandTestFixture.cs +++ b/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandTestFixture.cs @@ -1,3 +1,4 @@ +using System; using CleanArchitecture.Domain.Commands.Users.UpdateUser; using CleanArchitecture.Domain.Interfaces.Repositories; using Moq; diff --git a/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandValidationTests.cs b/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandValidationTests.cs index 9b06cac..e593959 100644 --- a/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandValidationTests.cs +++ b/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandValidationTests.cs @@ -1,3 +1,4 @@ +using System; using CleanArchitecture.Domain.Commands.Users.UpdateUser; using CleanArchitecture.Domain.Errors; using Xunit; diff --git a/CleanArchitecture.Domain.Tests/CommandHandlerFixtureBase.cs b/CleanArchitecture.Domain.Tests/CommandHandlerFixtureBase.cs index ddf2bf7..01964a0 100644 --- a/CleanArchitecture.Domain.Tests/CommandHandlerFixtureBase.cs +++ b/CleanArchitecture.Domain.Tests/CommandHandlerFixtureBase.cs @@ -1,3 +1,4 @@ +using System; using System.Linq.Expressions; using CleanArchitecture.Domain.Interfaces; using CleanArchitecture.Domain.Notifications; @@ -7,9 +8,9 @@ namespace CleanArchitecture.Domain.Tests; public class CommandHandlerFixtureBase { - public Mock Bus { get; protected set; } - public Mock UnitOfWork { get; protected set; } - public Mock NotificationHandler { get; protected set; } + protected Mock Bus { get; } + protected Mock UnitOfWork { get; } + protected Mock NotificationHandler { get; } protected CommandHandlerFixtureBase() { diff --git a/CleanArchitecture.Domain.Tests/ValidationTestBase.cs b/CleanArchitecture.Domain.Tests/ValidationTestBase.cs index a039d3d..7f985c8 100644 --- a/CleanArchitecture.Domain.Tests/ValidationTestBase.cs +++ b/CleanArchitecture.Domain.Tests/ValidationTestBase.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; +using System.Linq; using CleanArchitecture.Domain.Commands; using FluentAssertions; using FluentValidation; @@ -8,7 +10,7 @@ public class ValidationTestBase where TCommand : CommandBase where TValidation: AbstractValidator { - protected readonly TValidation _validation; + private readonly TValidation _validation; protected ValidationTestBase(TValidation validation) { diff --git a/CleanArchitecture.Domain/Commands/Users/CreateUser/CreateUserCommand.cs b/CleanArchitecture.Domain/Commands/Users/CreateUser/CreateUserCommand.cs index 3762540..6106289 100644 --- a/CleanArchitecture.Domain/Commands/Users/CreateUser/CreateUserCommand.cs +++ b/CleanArchitecture.Domain/Commands/Users/CreateUser/CreateUserCommand.cs @@ -4,7 +4,7 @@ namespace CleanArchitecture.Domain.Commands.Users.CreateUser; public sealed class CreateUserCommand : CommandBase { - private static readonly CreateUserCommandValidation _validation = new(); + private readonly CreateUserCommandValidation _validation = new(); public Guid UserId { get; } public string Email { get; } diff --git a/CleanArchitecture.Domain/Commands/Users/DeleteUser/DeleteUserCommand.cs b/CleanArchitecture.Domain/Commands/Users/DeleteUser/DeleteUserCommand.cs index 34277b1..a15d7d6 100644 --- a/CleanArchitecture.Domain/Commands/Users/DeleteUser/DeleteUserCommand.cs +++ b/CleanArchitecture.Domain/Commands/Users/DeleteUser/DeleteUserCommand.cs @@ -4,7 +4,7 @@ namespace CleanArchitecture.Domain.Commands.Users.DeleteUser; public sealed class DeleteUserCommand : CommandBase { - private static readonly DeleteUserCommandValidation _validation = new(); + private readonly DeleteUserCommandValidation _validation = new(); public Guid UserId { get; } diff --git a/CleanArchitecture.Infrastructure.Tests/CleanArchitecture.Infrastructure.Tests.csproj b/CleanArchitecture.Infrastructure.Tests/CleanArchitecture.Infrastructure.Tests.csproj index 1097e66..257e4ac 100644 --- a/CleanArchitecture.Infrastructure.Tests/CleanArchitecture.Infrastructure.Tests.csproj +++ b/CleanArchitecture.Infrastructure.Tests/CleanArchitecture.Infrastructure.Tests.csproj @@ -2,7 +2,6 @@ net7.0 - enable enable false diff --git a/CleanArchitecture.Infrastructure.Tests/DomainNotificationHandlerTests.cs b/CleanArchitecture.Infrastructure.Tests/DomainNotificationHandlerTests.cs index a03f826..95148af 100644 --- a/CleanArchitecture.Infrastructure.Tests/DomainNotificationHandlerTests.cs +++ b/CleanArchitecture.Infrastructure.Tests/DomainNotificationHandlerTests.cs @@ -35,7 +35,7 @@ public sealed class DomainNotificationHandlerTests var domainNotification = new DomainNotification(key, value, code); var domainNotificationHandler = new DomainNotificationHandler(); - domainNotificationHandler.Handle(domainNotification, default); + domainNotificationHandler.Handle(domainNotification); domainNotificationHandler.GetNotifications().Should().HaveCount(1); } diff --git a/CleanArchitecture.Infrastructure.Tests/DomainNotificationTests.cs b/CleanArchitecture.Infrastructure.Tests/DomainNotificationTests.cs index 913dd4d..d942a92 100644 --- a/CleanArchitecture.Infrastructure.Tests/DomainNotificationTests.cs +++ b/CleanArchitecture.Infrastructure.Tests/DomainNotificationTests.cs @@ -1,4 +1,5 @@ -using CleanArchitecture.Domain.Notifications; +using System; +using CleanArchitecture.Domain.Notifications; using FluentAssertions; using Xunit; diff --git a/CleanArchitecture.Infrastructure.Tests/InMemoryBusTests.cs b/CleanArchitecture.Infrastructure.Tests/InMemoryBusTests.cs index 7dc2567..f3ed4d8 100644 --- a/CleanArchitecture.Infrastructure.Tests/InMemoryBusTests.cs +++ b/CleanArchitecture.Infrastructure.Tests/InMemoryBusTests.cs @@ -1,3 +1,6 @@ +using System; +using System.Threading; +using System.Threading.Tasks; using CleanArchitecture.Domain.Commands.Users.DeleteUser; using CleanArchitecture.Domain.Events.User; using CleanArchitecture.Domain.Notifications; diff --git a/CleanArchitecture.Infrastructure.Tests/UnitOfWorkTests.cs b/CleanArchitecture.Infrastructure.Tests/UnitOfWorkTests.cs index 32f15da..2a0e51f 100644 --- a/CleanArchitecture.Infrastructure.Tests/UnitOfWorkTests.cs +++ b/CleanArchitecture.Infrastructure.Tests/UnitOfWorkTests.cs @@ -1,3 +1,6 @@ +using System; +using System.Threading; +using System.Threading.Tasks; using CleanArchitecture.Infrastructure.Database; using CleanArchitecture.Infrastructure.Tests.Fixtures; using FluentAssertions; @@ -37,7 +40,7 @@ public sealed class UnitOfWorkTests dbContextMock .Setup(x => x.SaveChangesAsync(CancellationToken.None)) - .Throws(new DbUpdateException("Boom", new System.Exception("it broke"))); + .Throws(new DbUpdateException("Boom", new Exception("it broke"))); var unitOfWork = UnitOfWorkTestFixture.GetUnitOfWork(dbContextMock.Object, loggerMock.Object); @@ -59,8 +62,8 @@ public sealed class UnitOfWorkTests var unitOfWork = UnitOfWorkTestFixture.GetUnitOfWork(dbContextMock.Object, loggerMock.Object); - Func knalltAction = async () => await unitOfWork.CommitAsync(); + Func throwsAction = async () => await unitOfWork.CommitAsync(); - await knalltAction.Should().ThrowAsync(); + await throwsAction.Should().ThrowAsync(); } } \ No newline at end of file diff --git a/CleanArchitecture.Infrastructure/Repositories/BaseRepository.cs b/CleanArchitecture.Infrastructure/Repositories/BaseRepository.cs index f18e513..52b768d 100644 --- a/CleanArchitecture.Infrastructure/Repositories/BaseRepository.cs +++ b/CleanArchitecture.Infrastructure/Repositories/BaseRepository.cs @@ -10,23 +10,23 @@ namespace CleanArchitecture.Infrastructure.Repositories; public class BaseRepository : IRepository where TEntity : Entity { - protected readonly DbContext _dbContext; - protected readonly DbSet _dbSet; + private readonly DbContext _dbContext; + protected readonly DbSet DbSet; - public BaseRepository(DbContext context) + protected BaseRepository(DbContext context) { _dbContext = context; - _dbSet = _dbContext.Set(); + DbSet = _dbContext.Set(); } public void Add(TEntity entity) { - _dbSet.Add(entity); + DbSet.Add(entity); } public void AddRange(IEnumerable entities) { - _dbSet.AddRange(entities); + DbSet.AddRange(entities); } public void Dispose() @@ -37,17 +37,17 @@ public class BaseRepository : IRepository where TEntity : Enti public virtual IQueryable GetAll() { - return _dbSet; + return DbSet; } public virtual IQueryable GetAllNoTracking() { - return _dbSet.AsNoTracking(); + return DbSet.AsNoTracking(); } public virtual async Task GetByIdAsync(Guid id) { - return await _dbSet.FindAsync(id); + return await DbSet.FindAsync(id); } public int SaveChanges() @@ -65,24 +65,24 @@ public class BaseRepository : IRepository where TEntity : Enti public virtual void Update(TEntity entity) { - _dbSet.Update(entity); + DbSet.Update(entity); } public Task ExistsAsync(Guid id) { - return _dbSet.AnyAsync(entity => entity.Id == id); + return DbSet.AnyAsync(entity => entity.Id == id); } public void Remove(TEntity entity, bool hardDelete = false) { if (hardDelete) { - _dbSet.Remove(entity); + DbSet.Remove(entity); } else { entity.Delete(); - _dbSet.Update(entity); + DbSet.Update(entity); } } diff --git a/CleanArchitecture.Infrastructure/Repositories/UserRepository.cs b/CleanArchitecture.Infrastructure/Repositories/UserRepository.cs index 1fb07a7..19976cf 100644 --- a/CleanArchitecture.Infrastructure/Repositories/UserRepository.cs +++ b/CleanArchitecture.Infrastructure/Repositories/UserRepository.cs @@ -14,6 +14,6 @@ public sealed class UserRepository : BaseRepository, IUserRepository public async Task GetByEmailAsync(string email) { - return await _dbSet.SingleOrDefaultAsync(user => user.Email == email); + return await DbSet.SingleOrDefaultAsync(user => user.Email == email); } } \ No newline at end of file diff --git a/CleanArchitecture.Infrastructure/UnitOfWork.cs b/CleanArchitecture.Infrastructure/UnitOfWork.cs index 0525866..97d88a9 100644 --- a/CleanArchitecture.Infrastructure/UnitOfWork.cs +++ b/CleanArchitecture.Infrastructure/UnitOfWork.cs @@ -6,7 +6,7 @@ using Microsoft.Extensions.Logging; namespace CleanArchitecture.Infrastructure; -public class UnitOfWork : IUnitOfWork where TContext : DbContext +public sealed class UnitOfWork : IUnitOfWork where TContext : DbContext { private readonly TContext _context; private readonly ILogger> _logger; @@ -34,10 +34,11 @@ public class UnitOfWork : IUnitOfWork where TContext : DbContext public void Dispose() { Dispose(true); + // ReSharper disable once GCSuppressFinalizeForTypeWithoutDestructor GC.SuppressFinalize(this); } - protected virtual void Dispose(bool disposing) + private void Dispose(bool disposing) { if (disposing) { diff --git a/CleanArchitecture.IntegrationTests/CleanArchitecture.IntegrationTests.csproj b/CleanArchitecture.IntegrationTests/CleanArchitecture.IntegrationTests.csproj index 255c2cf..08d7f1f 100644 --- a/CleanArchitecture.IntegrationTests/CleanArchitecture.IntegrationTests.csproj +++ b/CleanArchitecture.IntegrationTests/CleanArchitecture.IntegrationTests.csproj @@ -2,7 +2,6 @@ net7.0 - enable enable false diff --git a/CleanArchitecture.IntegrationTests/Controller/UserControllerTests.cs b/CleanArchitecture.IntegrationTests/Controller/UserControllerTests.cs index de56e73..fd8791b 100644 --- a/CleanArchitecture.IntegrationTests/Controller/UserControllerTests.cs +++ b/CleanArchitecture.IntegrationTests/Controller/UserControllerTests.cs @@ -1,4 +1,8 @@ -using System.Net; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading.Tasks; using CleanArchitecture.Application.ViewModels.Users; using CleanArchitecture.IntegrationTests.Extensions; using CleanArchitecture.IntegrationTests.Fixtures; @@ -8,7 +12,7 @@ using Xunit.Priority; namespace CleanArchitecture.IntegrationTests.Controller; -[Collection("Integrationtests")] +[Collection("IntegrationTests")] [TestCaseOrderer(PriorityOrderer.Name, PriorityOrderer.Assembly)] public sealed class UserControllerTests : IClassFixture { @@ -122,7 +126,7 @@ public sealed class UserControllerTests : IClassFixture message?.Data.Should().NotBeNull(); - var content = message!.Data!; + var content = message!.Data!.ToList(); content.Should().ContainSingle(); content.First().Id.Should().Be(_fixture.CreatedUserId); @@ -142,7 +146,7 @@ public sealed class UserControllerTests : IClassFixture message?.Data.Should().NotBeEmpty(); - var content = message!.Data!; + var content = message!.Data; content.Should().Be(_fixture.CreatedUserId); } diff --git a/CleanArchitecture.IntegrationTests/Extensions/FunctionalTestsServiceCollectionExtensions.cs b/CleanArchitecture.IntegrationTests/Extensions/FunctionalTestsServiceCollectionExtensions.cs index 7179db1..8cb7fad 100644 --- a/CleanArchitecture.IntegrationTests/Extensions/FunctionalTestsServiceCollectionExtensions.cs +++ b/CleanArchitecture.IntegrationTests/Extensions/FunctionalTestsServiceCollectionExtensions.cs @@ -1,4 +1,7 @@ -using System.Data.Common; +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Linq; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; @@ -17,7 +20,7 @@ public static class FunctionalTestsServiceCollectionExtensions services.AddScoped(p => DbContextOptionsFactory( p, - (sp, options) => options + (_, options) => options .ConfigureWarnings(b => b.Log(CoreEventId.ManyServiceProvidersCreatedWarning)) .UseLazyLoadingProxies() .UseSqlite(connection))); @@ -35,7 +38,7 @@ public static class FunctionalTestsServiceCollectionExtensions builder.UseApplicationServiceProvider(applicationServiceProvider); - optionsAction?.Invoke(applicationServiceProvider, builder); + optionsAction.Invoke(applicationServiceProvider, builder); return builder.Options; } diff --git a/CleanArchitecture.IntegrationTests/Extensions/HttpExtensions.cs b/CleanArchitecture.IntegrationTests/Extensions/HttpExtensions.cs index 45ace89..f765a9c 100644 --- a/CleanArchitecture.IntegrationTests/Extensions/HttpExtensions.cs +++ b/CleanArchitecture.IntegrationTests/Extensions/HttpExtensions.cs @@ -1,12 +1,14 @@ -using System.Text; +using System.Net.Http; +using System.Text; using System.Text.Json; +using System.Threading.Tasks; using CleanArchitecture.Api.Models; namespace CleanArchitecture.IntegrationTests.Extensions; -public static class HttpExensions +public static class HttpExtensions { - public static JsonSerializerOptions JsonSerializerOptions = new() + private static readonly JsonSerializerOptions JsonSerializerOptions = new() { PropertyNameCaseInsensitive = true, }; diff --git a/CleanArchitecture.IntegrationTests/Fixtures/TestFixtureBase.cs b/CleanArchitecture.IntegrationTests/Fixtures/TestFixtureBase.cs index afaa3d1..2d4994e 100644 --- a/CleanArchitecture.IntegrationTests/Fixtures/TestFixtureBase.cs +++ b/CleanArchitecture.IntegrationTests/Fixtures/TestFixtureBase.cs @@ -1,4 +1,7 @@ -using CleanArchitecture.Infrastructure.Database; +using System; +using System.IO; +using System.Net.Http; +using CleanArchitecture.Infrastructure.Database; using CleanArchitecture.IntegrationTests.Infrastructure; using Microsoft.Extensions.DependencyInjection; diff --git a/CleanArchitecture.IntegrationTests/Fixtures/UserTestFixture.cs b/CleanArchitecture.IntegrationTests/Fixtures/UserTestFixture.cs index 24bd329..5d31bea 100644 --- a/CleanArchitecture.IntegrationTests/Fixtures/UserTestFixture.cs +++ b/CleanArchitecture.IntegrationTests/Fixtures/UserTestFixture.cs @@ -1,4 +1,6 @@ -namespace CleanArchitecture.IntegrationTests.Fixtures; +using System; + +namespace CleanArchitecture.IntegrationTests.Fixtures; public sealed class UserTestFixture : TestFixtureBase { diff --git a/CleanArchitecture.IntegrationTests/Infrastructure/CleanArchitectureWebApplicationFactory.cs b/CleanArchitecture.IntegrationTests/Infrastructure/CleanArchitectureWebApplicationFactory.cs index 3a1dd7c..0e9f243 100644 --- a/CleanArchitecture.IntegrationTests/Infrastructure/CleanArchitectureWebApplicationFactory.cs +++ b/CleanArchitecture.IntegrationTests/Infrastructure/CleanArchitectureWebApplicationFactory.cs @@ -1,4 +1,5 @@ -using CleanArchitecture.Infrastructure.Database; +using System; +using CleanArchitecture.Infrastructure.Database; using CleanArchitecture.Infrastructure.Extensions; using CleanArchitecture.IntegrationTests.Extensions; using Microsoft.AspNetCore.Hosting; diff --git a/CleanArchitecture.Proto/CleanArchitecture.Proto.csproj b/CleanArchitecture.Proto/CleanArchitecture.Proto.csproj new file mode 100644 index 0000000..fa76384 --- /dev/null +++ b/CleanArchitecture.Proto/CleanArchitecture.Proto.csproj @@ -0,0 +1,24 @@ + + + + net7.0 + enable + + + + + + + + + + + + + + + + + + + diff --git a/CleanArchitecture.Proto/Users/Models.proto b/CleanArchitecture.Proto/Users/Models.proto new file mode 100644 index 0000000..b627309 --- /dev/null +++ b/CleanArchitecture.Proto/Users/Models.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +option csharp_namespace = "CleanArchitecture.Proto.Users"; + +message GrpcUser { + string id = 1; + string firstName = 3; + string lastName = 4; + string email = 5; + bool isDeleted = 6; +} \ No newline at end of file diff --git a/CleanArchitecture.Proto/Users/UsersApi.proto b/CleanArchitecture.Proto/Users/UsersApi.proto new file mode 100644 index 0000000..557b028 --- /dev/null +++ b/CleanArchitecture.Proto/Users/UsersApi.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +option csharp_namespace = "CleanArchitecture.Proto.Users"; + +import "Users/Models.proto"; + +service UsersApi { + rpc GetByIds(GetByIdsRequest) returns (GetByIdsResult); +} + +message GetByIdsResult { + repeated GrpcUser users = 1; +} + +message GetByIdsRequest { + repeated string ids = 1; +} diff --git a/CleanArchitecture.gRPC.Tests/CleanArchitecture.gRPC.Tests.csproj b/CleanArchitecture.gRPC.Tests/CleanArchitecture.gRPC.Tests.csproj new file mode 100644 index 0000000..732fc33 --- /dev/null +++ b/CleanArchitecture.gRPC.Tests/CleanArchitecture.gRPC.Tests.csproj @@ -0,0 +1,31 @@ + + + + net7.0 + enable + + false + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + diff --git a/CleanArchitecture.gRPC.Tests/Fixtures/UserTestsFixture.cs b/CleanArchitecture.gRPC.Tests/Fixtures/UserTestsFixture.cs new file mode 100644 index 0000000..63dd2bf --- /dev/null +++ b/CleanArchitecture.gRPC.Tests/Fixtures/UserTestsFixture.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using CleanArchitecture.Domain.Entities; +using CleanArchitecture.Domain.Interfaces.Repositories; +using MockQueryable.Moq; +using Moq; + +namespace CleanArchitecture.gRPC.Tests.Fixtures; + +public sealed class UserTestsFixture +{ + private Mock UserRepository { get; } = new (); + + public UsersApiImplementation UsersApiImplementation { get; } + + public IEnumerable ExistingUsers { get; } + + public UserTestsFixture() + { + ExistingUsers = new List() + { + new (Guid.NewGuid(), "test@test.de", "Test First Name", "Test Last Name"), + new (Guid.NewGuid(), "email@Email.de", "Email First Name", "Email Last Name"), + new (Guid.NewGuid(), "user@user.de", "User First Name", "User Last Name"), + }; + + var queryable = ExistingUsers.AsQueryable().BuildMock(); + + UserRepository + .Setup(repository => repository.GetAllNoTracking()) + .Returns(queryable); + + UsersApiImplementation = new UsersApiImplementation(UserRepository.Object); + } +} \ No newline at end of file diff --git a/CleanArchitecture.gRPC.Tests/Users/GetUsersByIdsTests.cs b/CleanArchitecture.gRPC.Tests/Users/GetUsersByIdsTests.cs new file mode 100644 index 0000000..5a4302b --- /dev/null +++ b/CleanArchitecture.gRPC.Tests/Users/GetUsersByIdsTests.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using CleanArchitecture.gRPC.Tests.Fixtures; +using CleanArchitecture.Proto.Users; +using FluentAssertions; +using Xunit; + +namespace CleanArchitecture.gRPC.Tests.Users; + +public sealed class GetUsersByIdsTests : IClassFixture +{ + private readonly UserTestsFixture _fixture; + + public GetUsersByIdsTests(UserTestsFixture fixture) + { + _fixture = fixture; + } + + [Fact] + public async Task Should_Get_Empty_List_If_No_Ids_Are_Given() + { + var result = await _fixture.UsersApiImplementation.GetByIds( + SetupRequest(Enumerable.Empty()), + null!); + + result.Users.Should().HaveCount(0); + } + + [Fact] + public async Task Should_Get_Requested_Asked_Ids() + { + var nonExistingId = Guid.NewGuid(); + + var ids = _fixture.ExistingUsers + .Take(2) + .Select(user => user.Id) + .ToList(); + + ids.Add(nonExistingId); + + var result = await _fixture.UsersApiImplementation.GetByIds( + SetupRequest(ids), + null!); + + result.Users.Should().HaveCount(2); + + foreach (var user in result.Users) + { + var userId = Guid.Parse(user.Id); + + userId.Should().NotBe(nonExistingId); + + var mockUser = _fixture.ExistingUsers.First(u => u.Id == userId); + + mockUser.Should().NotBeNull(); + + user.Email.Should().Be(mockUser.Email); + user.FirstName.Should().Be(mockUser.GivenName); + user.LastName.Should().Be(mockUser.Surname); + } + } + + private static GetByIdsRequest SetupRequest(IEnumerable ids) + { + var request = new GetByIdsRequest(); + + request.Ids.AddRange(ids.Select(id => id.ToString())); + request.Ids.Add("Not a guid"); + + return request; + } +} \ No newline at end of file diff --git a/CleanArchitecture.gRPC/CleanArchitecture.gRPC.csproj b/CleanArchitecture.gRPC/CleanArchitecture.gRPC.csproj new file mode 100644 index 0000000..65b4b52 --- /dev/null +++ b/CleanArchitecture.gRPC/CleanArchitecture.gRPC.csproj @@ -0,0 +1,17 @@ + + + + net7.0 + enable + + + + + + + + + + + + diff --git a/CleanArchitecture.gRPC/UsersApiImplementation.cs b/CleanArchitecture.gRPC/UsersApiImplementation.cs new file mode 100644 index 0000000..279bdfc --- /dev/null +++ b/CleanArchitecture.gRPC/UsersApiImplementation.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using CleanArchitecture.Domain.Interfaces.Repositories; +using CleanArchitecture.Proto.Users; +using Grpc.Core; +using Microsoft.EntityFrameworkCore; + +namespace CleanArchitecture.gRPC; + +public sealed class UsersApiImplementation : UsersApi.UsersApiBase +{ + private readonly IUserRepository _userRepository; + + public UsersApiImplementation(IUserRepository userRepository) + { + _userRepository = userRepository; + } + + public override async Task GetByIds( + GetByIdsRequest request, + ServerCallContext context) + { + var idsAsGuids = new List(request.Ids.Count); + + foreach (var id in request.Ids) + { + if (Guid.TryParse(id, out var parsed)) + { + idsAsGuids.Add(parsed); + } + } + + var users = await _userRepository + .GetAllNoTracking() + .Where(user => idsAsGuids.Contains(user.Id)) + .Select(user => new GrpcUser + { + Id = user.Id.ToString(), + Email = user.Email, + FirstName = user.GivenName, + LastName = user.Surname, + IsDeleted = user.Deleted + }) + .ToListAsync(); + + var result = new GetByIdsResult(); + + result.Users.AddRange(users); + + return result; + } +} \ No newline at end of file diff --git a/CleanArchitecture.sln b/CleanArchitecture.sln index 22483d0..31560fb 100644 --- a/CleanArchitecture.sln +++ b/CleanArchitecture.sln @@ -16,6 +16,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CleanArchitecture.Infrastru EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CleanArchitecture.IntegrationTests", "CleanArchitecture.IntegrationTests\CleanArchitecture.IntegrationTests.csproj", "{39732BD4-909F-410C-8737-1F9FE3E269A7}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CleanArchitecture.gRPC", "CleanArchitecture.gRPC\CleanArchitecture.gRPC.csproj", "{7A6353A9-B60C-4B13-A849-D21B315047EE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CleanArchitecture.Proto", "CleanArchitecture.Proto\CleanArchitecture.Proto.csproj", "{5F978903-7A7A-45C2-ABE0-C2906ECD326B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CleanArchitecture.gRPC.Tests", "CleanArchitecture.gRPC.Tests\CleanArchitecture.gRPC.Tests.csproj", "{E3A836DD-85DB-44FD-BC19-DDFE111D9EB0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -54,5 +60,17 @@ Global {39732BD4-909F-410C-8737-1F9FE3E269A7}.Debug|Any CPU.Build.0 = Debug|Any CPU {39732BD4-909F-410C-8737-1F9FE3E269A7}.Release|Any CPU.ActiveCfg = Release|Any CPU {39732BD4-909F-410C-8737-1F9FE3E269A7}.Release|Any CPU.Build.0 = Release|Any CPU + {7A6353A9-B60C-4B13-A849-D21B315047EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7A6353A9-B60C-4B13-A849-D21B315047EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7A6353A9-B60C-4B13-A849-D21B315047EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7A6353A9-B60C-4B13-A849-D21B315047EE}.Release|Any CPU.Build.0 = Release|Any CPU + {5F978903-7A7A-45C2-ABE0-C2906ECD326B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5F978903-7A7A-45C2-ABE0-C2906ECD326B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5F978903-7A7A-45C2-ABE0-C2906ECD326B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5F978903-7A7A-45C2-ABE0-C2906ECD326B}.Release|Any CPU.Build.0 = Release|Any CPU + {E3A836DD-85DB-44FD-BC19-DDFE111D9EB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E3A836DD-85DB-44FD-BC19-DDFE111D9EB0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E3A836DD-85DB-44FD-BC19-DDFE111D9EB0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E3A836DD-85DB-44FD-BC19-DDFE111D9EB0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/Todo.txt b/Todo.txt index 4d40328..ebb0118 100644 --- a/Todo.txt +++ b/Todo.txt @@ -1,3 +1,4 @@ - Remove warnings and apply suggestions -- Add gRPC support - Add authentication and authorization +- Utility integration tests +- Queryhandler tests for deleted users \ No newline at end of file