mirror of
https://github.com/alex289/CleanArchitecture.git
synced 2025-06-30 10:33:43 +00:00
Add tenant entity
This commit is contained in:
parent
65d15d383b
commit
b0d96d8b4d
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -46,6 +46,7 @@ public sealed class UserService : IUserService
|
||||
|
||||
await _bus.SendCommandAsync(new CreateUserCommand(
|
||||
userId,
|
||||
user.TenantId,
|
||||
user.Email,
|
||||
user.FirstName,
|
||||
user.LastName,
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -71,6 +71,7 @@ public sealed class UpdateUserCommandHandlerTests
|
||||
_fixture.UserRepository
|
||||
.GetByEmailAsync(command.Email)
|
||||
.Returns(new Entities.User(
|
||||
Guid.NewGuid(),
|
||||
Guid.NewGuid(),
|
||||
command.Email,
|
||||
"Some",
|
||||
|
@ -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",
|
||||
|
@ -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; }
|
||||
|
@ -61,6 +61,7 @@ public sealed class CreateUserCommandHandler : CommandHandlerBase,
|
||||
|
||||
var user = new User(
|
||||
request.UserId,
|
||||
request.TenantId,
|
||||
request.Email,
|
||||
request.FirstName,
|
||||
request.LastName,
|
||||
|
@ -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<CreateUserCo
|
||||
.EmailAddress()
|
||||
.WithErrorCode(DomainErrorCodes.UserInvalidEmail)
|
||||
.WithMessage("Email is not a valid email address")
|
||||
.MaximumLength(320)
|
||||
.MaximumLength(MaxLengths.User.Email)
|
||||
.WithErrorCode(DomainErrorCodes.UserEmailExceedsMaxLength)
|
||||
.WithMessage("Email may not be longer than 320 characters");
|
||||
}
|
||||
@ -40,7 +41,7 @@ public sealed class CreateUserCommandValidation : AbstractValidator<CreateUserCo
|
||||
.NotEmpty()
|
||||
.WithErrorCode(DomainErrorCodes.UserEmptyFirstName)
|
||||
.WithMessage("FirstName may not be empty")
|
||||
.MaximumLength(100)
|
||||
.MaximumLength(MaxLengths.User.FirstName)
|
||||
.WithErrorCode(DomainErrorCodes.UserFirstNameExceedsMaxLength)
|
||||
.WithMessage("FirstName may not be longer than 100 characters");
|
||||
}
|
||||
@ -51,7 +52,7 @@ public sealed class CreateUserCommandValidation : AbstractValidator<CreateUserCo
|
||||
.NotEmpty()
|
||||
.WithErrorCode(DomainErrorCodes.UserEmptyLastName)
|
||||
.WithMessage("LastName may not be empty")
|
||||
.MaximumLength(100)
|
||||
.MaximumLength(MaxLengths.User.LastName)
|
||||
.WithErrorCode(DomainErrorCodes.UserLastNameExceedsMaxLength)
|
||||
.WithMessage("LastName may not be longer than 100 characters");
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using CleanArchitecture.Domain.Errors;
|
||||
using CleanArchitecture.Domain.Constants;
|
||||
using CleanArchitecture.Domain.Errors;
|
||||
using CleanArchitecture.Domain.Extensions.Validation;
|
||||
using FluentValidation;
|
||||
|
||||
@ -18,7 +19,7 @@ public sealed class LoginUserCommandValidation : AbstractValidator<LoginUserComm
|
||||
.EmailAddress()
|
||||
.WithErrorCode(DomainErrorCodes.UserInvalidEmail)
|
||||
.WithMessage("Email is not a valid email address")
|
||||
.MaximumLength(320)
|
||||
.MaximumLength(MaxLengths.User.Email)
|
||||
.WithErrorCode(DomainErrorCodes.UserEmailExceedsMaxLength)
|
||||
.WithMessage("Email may not be longer than 320 characters");
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
using CleanArchitecture.Domain.Constants;
|
||||
using CleanArchitecture.Domain.Errors;
|
||||
using FluentValidation;
|
||||
|
||||
@ -28,7 +29,7 @@ public sealed class UpdateUserCommandValidation : AbstractValidator<UpdateUserCo
|
||||
.EmailAddress()
|
||||
.WithErrorCode(DomainErrorCodes.UserInvalidEmail)
|
||||
.WithMessage("Email is not a valid email address")
|
||||
.MaximumLength(320)
|
||||
.MaximumLength(MaxLengths.User.Email)
|
||||
.WithErrorCode(DomainErrorCodes.UserEmailExceedsMaxLength)
|
||||
.WithMessage("Email may not be longer than 320 characters");
|
||||
}
|
||||
@ -39,7 +40,7 @@ public sealed class UpdateUserCommandValidation : AbstractValidator<UpdateUserCo
|
||||
.NotEmpty()
|
||||
.WithErrorCode(DomainErrorCodes.UserEmptyFirstName)
|
||||
.WithMessage("FirstName may not be empty")
|
||||
.MaximumLength(100)
|
||||
.MaximumLength(MaxLengths.User.FirstName)
|
||||
.WithErrorCode(DomainErrorCodes.UserFirstNameExceedsMaxLength)
|
||||
.WithMessage("FirstName may not be longer than 100 characters");
|
||||
}
|
||||
@ -50,7 +51,7 @@ public sealed class UpdateUserCommandValidation : AbstractValidator<UpdateUserCo
|
||||
.NotEmpty()
|
||||
.WithErrorCode(DomainErrorCodes.UserEmptyLastName)
|
||||
.WithMessage("LastName may not be empty")
|
||||
.MaximumLength(100)
|
||||
.MaximumLength(MaxLengths.User.LastName)
|
||||
.WithErrorCode(DomainErrorCodes.UserLastNameExceedsMaxLength)
|
||||
.WithMessage("LastName may not be longer than 100 characters");
|
||||
}
|
||||
|
12
CleanArchitecture.Domain/Constants/Ids.cs
Normal file
12
CleanArchitecture.Domain/Constants/Ids.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace CleanArchitecture.Domain.Constants;
|
||||
|
||||
public static class Ids
|
||||
{
|
||||
public static class Seed
|
||||
{
|
||||
public static readonly Guid UserId = new("7e3892c0-9374-49fa-a3fd-53db637a40ae");
|
||||
public static readonly Guid TenantId = new("b542bf25-134c-47a2-a0df-84ed14d03c4a");
|
||||
}
|
||||
}
|
17
CleanArchitecture.Domain/Constants/MaxLengths.cs
Normal file
17
CleanArchitecture.Domain/Constants/MaxLengths.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace CleanArchitecture.Domain.Constants;
|
||||
|
||||
public sealed class MaxLengths
|
||||
{
|
||||
public static class User
|
||||
{
|
||||
public const int Email = 320;
|
||||
public const int FirstName = 100;
|
||||
public const int LastName = 100;
|
||||
public const int Password = 128;
|
||||
}
|
||||
|
||||
public static class Tenant
|
||||
{
|
||||
public const int Name = 255;
|
||||
}
|
||||
}
|
18
CleanArchitecture.Domain/Entities/Tenant.cs
Normal file
18
CleanArchitecture.Domain/Entities/Tenant.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CleanArchitecture.Domain.Entities;
|
||||
|
||||
public class Tenant : Entity
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
|
||||
public ICollection<User> Users { get; private set; } = new HashSet<User>();
|
||||
|
||||
public Tenant(
|
||||
Guid id,
|
||||
string name) : base(id)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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<Tenant>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Tenant> builder)
|
||||
{
|
||||
builder
|
||||
.Property(user => user.Name)
|
||||
.IsRequired()
|
||||
.HasMaxLength(MaxLengths.Tenant.Name);
|
||||
|
||||
builder.HasData(new Tenant(
|
||||
Ids.Seed.TenantId,
|
||||
"Admin Tenant"));
|
||||
}
|
||||
}
|
@ -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<User>
|
||||
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",
|
||||
|
@ -11,9 +11,11 @@ public class ApplicationDbContext : DbContext
|
||||
}
|
||||
|
||||
public DbSet<User> Users { get; set; } = null!;
|
||||
public DbSet<Tenant> Tenants { get; set; } = null!;
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
builder.ApplyConfiguration(new UserConfiguration());
|
||||
builder.ApplyConfiguration(new TenantConfiguration());
|
||||
}
|
||||
}
|
@ -32,7 +32,8 @@ public sealed class UserControllerTests : IClassFixture<UserTestFixture>
|
||||
_fixture.CreatedUserEmail,
|
||||
"Test",
|
||||
"Email",
|
||||
_fixture.CreatedUserPassword);
|
||||
_fixture.CreatedUserPassword,
|
||||
Guid.NewGuid());
|
||||
|
||||
var response = await _fixture.ServerClient.PostAsJsonAsync("/api/v1/user", user);
|
||||
|
||||
|
@ -33,6 +33,7 @@ public sealed class GetUsersByIdsTestFixture : TestFixtureBase
|
||||
{
|
||||
return new User(
|
||||
CreatedUserId,
|
||||
Guid.NewGuid(),
|
||||
"user@user.de",
|
||||
"User First Name",
|
||||
"User Last Name",
|
||||
|
@ -16,6 +16,7 @@ public sealed class UserTestsFixture
|
||||
ExistingUsers = new List<User>
|
||||
{
|
||||
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",
|
||||
|
Loading…
Reference in New Issue
Block a user