diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/AbpTenantValidator.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/AbpTenantValidator.cs new file mode 100644 index 0000000000..badd9515b8 --- /dev/null +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/AbpTenantValidator.cs @@ -0,0 +1,26 @@ +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.TenantManagement; + +public class AbpTenantValidator : ITenantValidator, ITransientDependency +{ + protected ITenantRepository TenantRepository { get; } + + public AbpTenantValidator(ITenantRepository tenantRepository) + { + TenantRepository = tenantRepository; + } + + public virtual async Task ValidateAsync(Tenant tenant) + { + Check.NotNullOrWhiteSpace(tenant.Name, nameof(tenant.Name)); + Check.NotNullOrWhiteSpace(tenant.NormalizedName, nameof(tenant.NormalizedName)); + + var owner = await TenantRepository.FindByNameAsync(tenant.NormalizedName); + if (owner != null && owner.Id != tenant.Id) + { + throw new BusinessException("Volo.Abp.TenantManagement:DuplicateTenantName").WithData("Name", tenant.NormalizedName); + } + } +} diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantValidator.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantValidator.cs new file mode 100644 index 0000000000..3a5cc9ffb0 --- /dev/null +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantValidator.cs @@ -0,0 +1,8 @@ +using System.Threading.Tasks; + +namespace Volo.Abp.TenantManagement; + +public interface ITenantValidator +{ + Task ValidateAsync(Tenant tenant); +} diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs index 0f40cfdd0b..91cdf87abb 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs @@ -1,6 +1,4 @@ -using System; -using System.Threading.Tasks; -using Volo.Abp.Caching; +using System.Threading.Tasks; using Volo.Abp.Domain.Services; using Volo.Abp.EventBus.Local; using Volo.Abp.MultiTenancy; @@ -9,16 +7,16 @@ namespace Volo.Abp.TenantManagement; public class TenantManager : DomainService, ITenantManager { - protected ITenantRepository TenantRepository { get; } + protected ITenantValidator TenantValidator { get; } protected ITenantNormalizer TenantNormalizer { get; } protected ILocalEventBus LocalEventBus { get; } public TenantManager( - ITenantRepository tenantRepository, + ITenantValidator tenantValidator, ITenantNormalizer tenantNormalizer, ILocalEventBus localEventBus) { - TenantRepository = tenantRepository; + TenantValidator = tenantValidator; TenantNormalizer = tenantNormalizer; LocalEventBus = localEventBus; } @@ -27,9 +25,9 @@ public class TenantManager : DomainService, ITenantManager { Check.NotNull(name, nameof(name)); - var normalizedName = TenantNormalizer.NormalizeName(name); - await ValidateNameAsync(normalizedName); - return new Tenant(GuidGenerator.Create(), name, normalizedName); + var tenant = new Tenant(GuidGenerator.Create(), name, TenantNormalizer.NormalizeName(name)); + await TenantValidator.ValidateAsync(tenant); + return tenant; } public virtual async Task ChangeNameAsync(Tenant tenant, string name) @@ -37,20 +35,10 @@ public class TenantManager : DomainService, ITenantManager Check.NotNull(tenant, nameof(tenant)); Check.NotNull(name, nameof(name)); - var normalizedName = TenantNormalizer.NormalizeName(name); - - await ValidateNameAsync(normalizedName, tenant.Id); await LocalEventBus.PublishAsync(new TenantChangedEvent(tenant.Id, tenant.NormalizedName)); - tenant.SetName(name); - tenant.SetNormalizedName(normalizedName); - } - protected virtual async Task ValidateNameAsync(string normalizeName, Guid? expectedId = null) - { - var tenant = await TenantRepository.FindByNameAsync(normalizeName); - if (tenant != null && tenant.Id != expectedId) - { - throw new BusinessException("Volo.Abp.TenantManagement:DuplicateTenantName").WithData("Name", normalizeName); - } + tenant.SetName(name); + tenant.SetNormalizedName( TenantNormalizer.NormalizeName(name)); + await TenantValidator.ValidateAsync(tenant); } } diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantNameValidator_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantNameValidator_Tests.cs new file mode 100644 index 0000000000..bc1477d1ff --- /dev/null +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantNameValidator_Tests.cs @@ -0,0 +1,47 @@ +using System; +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace Volo.Abp.TenantManagement; + +public class TenantValidator_Tests : AbpTenantManagementDomainTestBase +{ + private readonly TenantManager _tenantManager; + private readonly ITenantRepository _tenantRepository; + + public TenantValidator_Tests() + { + _tenantManager = GetRequiredService(); + _tenantRepository = GetRequiredService(); + } + + [Fact] + public async Task Should_Throw_If_Name_Is_Null() + { + await Assert.ThrowsAsync(() => _tenantManager.CreateAsync("")); + } + + [Fact] + public async Task Should_Throw_If_Duplicate_Name() + { + await Assert.ThrowsAsync(() => _tenantManager.CreateAsync("VOLOSOFT")); + + var tenant = await _tenantRepository.FindByNameAsync("ABP"); + await Assert.ThrowsAsync(() => _tenantManager.ChangeNameAsync(tenant, "VOLOSOFT")); + } + + [Fact] + public async Task Should_Not_Throw_For_Unique_Name() + { + var tenant = await _tenantManager.CreateAsync("VOLOSOFT2"); + await _tenantRepository.InsertAsync(tenant); + + tenant = await _tenantRepository.FindByNameAsync("ABP"); + await _tenantManager.ChangeNameAsync(tenant, "VOLOSOFT3"); + await _tenantRepository.UpdateAsync(tenant); + + tenant = await _tenantRepository.FindByNameAsync("VOLOSOFT3"); + tenant.ShouldNotBeNull(); + } +}