From b0d96d8b4d240f7e3b4bc0f1f2b3fe9a23101fbc Mon Sep 17 00:00:00 2001 From: alex289 Date: Sun, 27 Aug 2023 19:09:23 +0200 Subject: [PATCH] Add tenant entity --- .../Queries/Users/GetAllUsersTestFixture.cs | 2 + .../Queries/Users/GetUserByIdTestFixture.cs | 2 + .../Services/UserService.cs | 1 + .../ChangePasswordCommandTestFixture.cs | 1 + .../CreateUserCommandHandlerTests.cs | 2 + .../CreateUserCommandTestFixture.cs | 1 + .../CreateUserCommandValidationTests.cs | 2 + .../DeleteUserCommandTestFixture.cs | 1 + .../LoginUser/LoginUserCommandTestFixture.cs | 1 + .../UpdateUserCommandHandlerTests.cs | 1 + .../UpdateUserCommandTestFixture.cs | 1 + .../Users/CreateUser/CreateUserCommand.cs | 3 + .../CreateUser/CreateUserCommandHandler.cs | 1 + .../CreateUser/CreateUserCommandValidation.cs | 7 +- .../LoginUser/LoginUserCommandValidation.cs | 5 +- .../UpdateUser/UpdateUserCommandValidation.cs | 7 +- CleanArchitecture.Domain/Constants/Ids.cs | 12 +++ .../Constants/MaxLengths.cs | 17 ++++ CleanArchitecture.Domain/Entities/Tenant.cs | 18 ++++ CleanArchitecture.Domain/Entities/User.cs | 83 +++++-------------- .../Configurations/TenantConfiguration.cs | 21 +++++ .../Configurations/UserConfiguration.cs | 12 +-- .../Database/ApplicationDbContext.cs | 2 + .../Controller/UserControllerTests.cs | 3 +- .../Fixtures/gRPC/GetUsersByIdsTestFixture.cs | 1 + .../Fixtures/UserTestsFixture.cs | 3 + 26 files changed, 133 insertions(+), 77 deletions(-) create mode 100644 CleanArchitecture.Domain/Constants/Ids.cs create mode 100644 CleanArchitecture.Domain/Constants/MaxLengths.cs create mode 100644 CleanArchitecture.Domain/Entities/Tenant.cs create mode 100644 CleanArchitecture.Infrastructure/Configurations/TenantConfiguration.cs diff --git a/CleanArchitecture.Application.Tests/Fixtures/Queries/Users/GetAllUsersTestFixture.cs b/CleanArchitecture.Application.Tests/Fixtures/Queries/Users/GetAllUsersTestFixture.cs index 0e23086..027e8ff 100644 --- a/CleanArchitecture.Application.Tests/Fixtures/Queries/Users/GetAllUsersTestFixture.cs +++ b/CleanArchitecture.Application.Tests/Fixtures/Queries/Users/GetAllUsersTestFixture.cs @@ -25,6 +25,7 @@ public sealed class GetAllUsersTestFixture : QueryHandlerBaseFixture { var user = new User( ExistingUserId, + Guid.NewGuid(), "max@mustermann.com", "Max", "Mustermann", @@ -40,6 +41,7 @@ public sealed class GetAllUsersTestFixture : QueryHandlerBaseFixture { var user = new User( ExistingUserId, + Guid.NewGuid(), "max@mustermann.com", "Max", "Mustermann", diff --git a/CleanArchitecture.Application.Tests/Fixtures/Queries/Users/GetUserByIdTestFixture.cs b/CleanArchitecture.Application.Tests/Fixtures/Queries/Users/GetUserByIdTestFixture.cs index 741faac..6f306d6 100644 --- a/CleanArchitecture.Application.Tests/Fixtures/Queries/Users/GetUserByIdTestFixture.cs +++ b/CleanArchitecture.Application.Tests/Fixtures/Queries/Users/GetUserByIdTestFixture.cs @@ -26,6 +26,7 @@ public sealed class GetUserByIdTestFixture : QueryHandlerBaseFixture { var user = new User( ExistingUserId, + Guid.NewGuid(), "max@mustermann.com", "Max", "Mustermann", @@ -41,6 +42,7 @@ public sealed class GetUserByIdTestFixture : QueryHandlerBaseFixture { var user = new User( ExistingUserId, + Guid.NewGuid(), "max@mustermann.com", "Max", "Mustermann", diff --git a/CleanArchitecture.Application/Services/UserService.cs b/CleanArchitecture.Application/Services/UserService.cs index 8ab4600..13920c7 100644 --- a/CleanArchitecture.Application/Services/UserService.cs +++ b/CleanArchitecture.Application/Services/UserService.cs @@ -46,6 +46,7 @@ public sealed class UserService : IUserService await _bus.SendCommandAsync(new CreateUserCommand( userId, + user.TenantId, user.Email, user.FirstName, user.LastName, diff --git a/CleanArchitecture.Domain.Tests/CommandHandler/User/ChangePassword/ChangePasswordCommandTestFixture.cs b/CleanArchitecture.Domain.Tests/CommandHandler/User/ChangePassword/ChangePasswordCommandTestFixture.cs index 20e2189..314716b 100644 --- a/CleanArchitecture.Domain.Tests/CommandHandler/User/ChangePassword/ChangePasswordCommandTestFixture.cs +++ b/CleanArchitecture.Domain.Tests/CommandHandler/User/ChangePassword/ChangePasswordCommandTestFixture.cs @@ -27,6 +27,7 @@ public sealed class ChangePasswordCommandTestFixture : CommandHandlerFixtureBase public Entities.User SetupUser() { var user = new Entities.User( + Guid.NewGuid(), Guid.NewGuid(), "max@mustermann.com", "Max", diff --git a/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandHandlerTests.cs b/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandHandlerTests.cs index 9319274..b902a98 100644 --- a/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandHandlerTests.cs +++ b/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandHandlerTests.cs @@ -16,6 +16,7 @@ public sealed class CreateUserCommandHandlerTests _fixture.SetupUser(); var command = new CreateUserCommand( + Guid.NewGuid(), Guid.NewGuid(), "test@email.com", "Test", @@ -37,6 +38,7 @@ public sealed class CreateUserCommandHandlerTests var command = new CreateUserCommand( user.Id, + Guid.NewGuid(), "test@email.com", "Test", "Email", diff --git a/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandTestFixture.cs b/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandTestFixture.cs index 3662b65..31ea40e 100644 --- a/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandTestFixture.cs +++ b/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandTestFixture.cs @@ -25,6 +25,7 @@ public sealed class CreateUserCommandTestFixture : CommandHandlerFixtureBase public Entities.User SetupUser() { var user = new Entities.User( + Guid.NewGuid(), Guid.NewGuid(), "max@mustermann.com", "Max", diff --git a/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandValidationTests.cs b/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandValidationTests.cs index f4635df..7906a1f 100644 --- a/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandValidationTests.cs +++ b/CleanArchitecture.Domain.Tests/CommandHandler/User/CreateUser/CreateUserCommandValidationTests.cs @@ -178,6 +178,7 @@ public sealed class CreateUserCommandValidationTests : private static CreateUserCommand CreateTestCommand( Guid? userId = null, + Guid? tenantId = null, string? email = null, string? firstName = null, string? lastName = null, @@ -185,6 +186,7 @@ public sealed class CreateUserCommandValidationTests : { return new( userId ?? Guid.NewGuid(), + tenantId ?? Guid.NewGuid(), email ?? "test@email.com", firstName ?? "test", lastName ?? "email", diff --git a/CleanArchitecture.Domain.Tests/CommandHandler/User/DeleteUser/DeleteUserCommandTestFixture.cs b/CleanArchitecture.Domain.Tests/CommandHandler/User/DeleteUser/DeleteUserCommandTestFixture.cs index 92af9a4..89c4eee 100644 --- a/CleanArchitecture.Domain.Tests/CommandHandler/User/DeleteUser/DeleteUserCommandTestFixture.cs +++ b/CleanArchitecture.Domain.Tests/CommandHandler/User/DeleteUser/DeleteUserCommandTestFixture.cs @@ -26,6 +26,7 @@ public sealed class DeleteUserCommandTestFixture : CommandHandlerFixtureBase public Entities.User SetupUser() { var user = new Entities.User( + Guid.NewGuid(), Guid.NewGuid(), "max@mustermann.com", "Max", diff --git a/CleanArchitecture.Domain.Tests/CommandHandler/User/LoginUser/LoginUserCommandTestFixture.cs b/CleanArchitecture.Domain.Tests/CommandHandler/User/LoginUser/LoginUserCommandTestFixture.cs index c8f91cd..7a08da8 100644 --- a/CleanArchitecture.Domain.Tests/CommandHandler/User/LoginUser/LoginUserCommandTestFixture.cs +++ b/CleanArchitecture.Domain.Tests/CommandHandler/User/LoginUser/LoginUserCommandTestFixture.cs @@ -37,6 +37,7 @@ public sealed class LoginUserCommandTestFixture : CommandHandlerFixtureBase public Entities.User SetupUser() { var user = new Entities.User( + Guid.NewGuid(), Guid.NewGuid(), "max@mustermann.com", "Max", diff --git a/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandHandlerTests.cs b/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandHandlerTests.cs index 841c796..66281d3 100644 --- a/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandHandlerTests.cs +++ b/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandHandlerTests.cs @@ -71,6 +71,7 @@ public sealed class UpdateUserCommandHandlerTests _fixture.UserRepository .GetByEmailAsync(command.Email) .Returns(new Entities.User( + Guid.NewGuid(), Guid.NewGuid(), command.Email, "Some", diff --git a/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandTestFixture.cs b/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandTestFixture.cs index cd21e9f..aaf9faf 100644 --- a/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandTestFixture.cs +++ b/CleanArchitecture.Domain.Tests/CommandHandler/User/UpdateUser/UpdateUserCommandTestFixture.cs @@ -26,6 +26,7 @@ public sealed class UpdateUserCommandTestFixture : CommandHandlerFixtureBase public Entities.User SetupUser() { var user = new Entities.User( + Guid.NewGuid(), Guid.NewGuid(), "max@mustermann.com", "Max", diff --git a/CleanArchitecture.Domain/Commands/Users/CreateUser/CreateUserCommand.cs b/CleanArchitecture.Domain/Commands/Users/CreateUser/CreateUserCommand.cs index c9e9e79..62406ad 100644 --- a/CleanArchitecture.Domain/Commands/Users/CreateUser/CreateUserCommand.cs +++ b/CleanArchitecture.Domain/Commands/Users/CreateUser/CreateUserCommand.cs @@ -8,12 +8,14 @@ public sealed class CreateUserCommand : CommandBase public CreateUserCommand( Guid userId, + Guid tenantId, string email, string firstName, string lastName, string password) : base(userId) { UserId = userId; + TenantId = tenantId; Email = email; FirstName = firstName; LastName = lastName; @@ -21,6 +23,7 @@ public sealed class CreateUserCommand : CommandBase } public Guid UserId { get; } + public Guid TenantId { get; } public string Email { get; } public string FirstName { get; } public string LastName { get; } diff --git a/CleanArchitecture.Domain/Commands/Users/CreateUser/CreateUserCommandHandler.cs b/CleanArchitecture.Domain/Commands/Users/CreateUser/CreateUserCommandHandler.cs index 98e1b2b..464aad4 100644 --- a/CleanArchitecture.Domain/Commands/Users/CreateUser/CreateUserCommandHandler.cs +++ b/CleanArchitecture.Domain/Commands/Users/CreateUser/CreateUserCommandHandler.cs @@ -61,6 +61,7 @@ public sealed class CreateUserCommandHandler : CommandHandlerBase, var user = new User( request.UserId, + request.TenantId, request.Email, request.FirstName, request.LastName, diff --git a/CleanArchitecture.Domain/Commands/Users/CreateUser/CreateUserCommandValidation.cs b/CleanArchitecture.Domain/Commands/Users/CreateUser/CreateUserCommandValidation.cs index 196db14..5a51947 100644 --- a/CleanArchitecture.Domain/Commands/Users/CreateUser/CreateUserCommandValidation.cs +++ b/CleanArchitecture.Domain/Commands/Users/CreateUser/CreateUserCommandValidation.cs @@ -1,3 +1,4 @@ +using CleanArchitecture.Domain.Constants; using CleanArchitecture.Domain.Errors; using CleanArchitecture.Domain.Extensions.Validation; using FluentValidation; @@ -29,7 +30,7 @@ public sealed class CreateUserCommandValidation : AbstractValidator Users { get; private set; } = new HashSet(); + + public Tenant( + Guid id, + string name) : base(id) + { + Name = name; + } +} \ No newline at end of file diff --git a/CleanArchitecture.Domain/Entities/User.cs b/CleanArchitecture.Domain/Entities/User.cs index 186913e..916269c 100644 --- a/CleanArchitecture.Domain/Entities/User.cs +++ b/CleanArchitecture.Domain/Entities/User.cs @@ -6,21 +6,6 @@ namespace CleanArchitecture.Domain.Entities; public class User : Entity { - public User( - Guid id, - string email, - string firstName, - string lastName, - string password, - UserRole role) : base(id) - { - Email = email; - FirstName = firstName; - LastName = lastName; - Password = password; - Role = role; - } - public string Email { get; private set; } public string FirstName { get; private set; } public string LastName { get; private set; } @@ -29,71 +14,43 @@ public class User : Entity public string FullName => $"{FirstName}, {LastName}"; - [MemberNotNull(nameof(Email))] + public Guid TenantId { get; private set; } + public Tenant Tenant { get; private set; } = null!; + + public User( + Guid id, + Guid tenantId, + string email, + string firstName, + string lastName, + string password, + UserRole role) : base(id) + { + Email = email; + TenantId = tenantId; + FirstName = firstName; + LastName = lastName; + Password = password; + Role = role; + } + public void SetEmail(string email) { - if (email == null) - { - throw new ArgumentNullException(nameof(email)); - } - - if (email.Length > 320) - { - throw new ArgumentException( - "Email may not be longer than 320 characters."); - } - Email = email; } - [MemberNotNull(nameof(FirstName))] public void SetFirstName(string firstName) { - if (firstName == null) - { - throw new ArgumentNullException(nameof(firstName)); - } - - if (firstName.Length > 100) - { - throw new ArgumentException( - "First name may not be longer than 100 characters"); - } - FirstName = firstName; } - [MemberNotNull(nameof(LastName))] public void SetLastName(string lastName) { - if (lastName == null) - { - throw new ArgumentNullException(nameof(lastName)); - } - - if (lastName.Length > 100) - { - throw new ArgumentException( - "Last name may not be longer than 100 characters"); - } - LastName = lastName; } - [MemberNotNull(nameof(Password))] public void SetPassword(string password) { - if (password == null) - { - throw new ArgumentNullException(nameof(password)); - } - - if (password.Length > 100) - { - throw new ArgumentException( - "Password may not be longer than 100 characters"); - } - Password = password; } diff --git a/CleanArchitecture.Infrastructure/Configurations/TenantConfiguration.cs b/CleanArchitecture.Infrastructure/Configurations/TenantConfiguration.cs new file mode 100644 index 0000000..783c4a7 --- /dev/null +++ b/CleanArchitecture.Infrastructure/Configurations/TenantConfiguration.cs @@ -0,0 +1,21 @@ +using CleanArchitecture.Domain.Constants; +using CleanArchitecture.Domain.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace CleanArchitecture.Infrastructure.Configurations; + +public sealed class TenantConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder + .Property(user => user.Name) + .IsRequired() + .HasMaxLength(MaxLengths.Tenant.Name); + + builder.HasData(new Tenant( + Ids.Seed.TenantId, + "Admin Tenant")); + } +} \ No newline at end of file diff --git a/CleanArchitecture.Infrastructure/Configurations/UserConfiguration.cs b/CleanArchitecture.Infrastructure/Configurations/UserConfiguration.cs index ecd3505..abe3cef 100644 --- a/CleanArchitecture.Infrastructure/Configurations/UserConfiguration.cs +++ b/CleanArchitecture.Infrastructure/Configurations/UserConfiguration.cs @@ -1,4 +1,5 @@ using System; +using CleanArchitecture.Domain.Constants; using CleanArchitecture.Domain.Entities; using CleanArchitecture.Domain.Enums; using Microsoft.EntityFrameworkCore; @@ -13,25 +14,26 @@ public sealed class UserConfiguration : IEntityTypeConfiguration builder .Property(user => user.Email) .IsRequired() - .HasMaxLength(320); + .HasMaxLength(MaxLengths.User.Email); builder .Property(user => user.FirstName) .IsRequired() - .HasMaxLength(100); + .HasMaxLength(MaxLengths.User.FirstName); builder .Property(user => user.LastName) .IsRequired() - .HasMaxLength(100); + .HasMaxLength(MaxLengths.User.LastName); builder .Property(user => user.Password) .IsRequired() - .HasMaxLength(128); + .HasMaxLength(MaxLengths.User.Password); builder.HasData(new User( - Guid.NewGuid(), + Ids.Seed.UserId, + Ids.Seed.TenantId, "admin@email.com", "Admin", "User", diff --git a/CleanArchitecture.Infrastructure/Database/ApplicationDbContext.cs b/CleanArchitecture.Infrastructure/Database/ApplicationDbContext.cs index 4280c4d..f2dea27 100644 --- a/CleanArchitecture.Infrastructure/Database/ApplicationDbContext.cs +++ b/CleanArchitecture.Infrastructure/Database/ApplicationDbContext.cs @@ -11,9 +11,11 @@ public class ApplicationDbContext : DbContext } public DbSet Users { get; set; } = null!; + public DbSet Tenants { get; set; } = null!; protected override void OnModelCreating(ModelBuilder builder) { builder.ApplyConfiguration(new UserConfiguration()); + builder.ApplyConfiguration(new TenantConfiguration()); } } \ No newline at end of file diff --git a/CleanArchitecture.IntegrationTests/Controller/UserControllerTests.cs b/CleanArchitecture.IntegrationTests/Controller/UserControllerTests.cs index ad2cb37..8a90362 100644 --- a/CleanArchitecture.IntegrationTests/Controller/UserControllerTests.cs +++ b/CleanArchitecture.IntegrationTests/Controller/UserControllerTests.cs @@ -32,7 +32,8 @@ public sealed class UserControllerTests : IClassFixture _fixture.CreatedUserEmail, "Test", "Email", - _fixture.CreatedUserPassword); + _fixture.CreatedUserPassword, + Guid.NewGuid()); var response = await _fixture.ServerClient.PostAsJsonAsync("/api/v1/user", user); diff --git a/CleanArchitecture.IntegrationTests/Fixtures/gRPC/GetUsersByIdsTestFixture.cs b/CleanArchitecture.IntegrationTests/Fixtures/gRPC/GetUsersByIdsTestFixture.cs index df677db..b06aecd 100644 --- a/CleanArchitecture.IntegrationTests/Fixtures/gRPC/GetUsersByIdsTestFixture.cs +++ b/CleanArchitecture.IntegrationTests/Fixtures/gRPC/GetUsersByIdsTestFixture.cs @@ -33,6 +33,7 @@ public sealed class GetUsersByIdsTestFixture : TestFixtureBase { return new User( CreatedUserId, + Guid.NewGuid(), "user@user.de", "User First Name", "User Last Name", diff --git a/CleanArchitecture.gRPC.Tests/Fixtures/UserTestsFixture.cs b/CleanArchitecture.gRPC.Tests/Fixtures/UserTestsFixture.cs index 6ecba91..d0616f2 100644 --- a/CleanArchitecture.gRPC.Tests/Fixtures/UserTestsFixture.cs +++ b/CleanArchitecture.gRPC.Tests/Fixtures/UserTestsFixture.cs @@ -16,6 +16,7 @@ public sealed class UserTestsFixture ExistingUsers = new List { new( + Guid.NewGuid(), Guid.NewGuid(), "test@test.de", "Test First Name", @@ -23,6 +24,7 @@ public sealed class UserTestsFixture "Test Password", UserRole.User), new( + Guid.NewGuid(), Guid.NewGuid(), "email@Email.de", "Email First Name", @@ -30,6 +32,7 @@ public sealed class UserTestsFixture "Email Password", UserRole.Admin), new( + Guid.NewGuid(), Guid.NewGuid(), "user@user.de", "User First Name",