Browse Source

use file-scoped namespacing for tenantManagement module

pull/10696/head
Ahmet Çotur 5 years ago
parent
commit
195138d552
  1. 45
      modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/AbpTenantManagementApplicationContractsModule.cs
  2. 31
      modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/AbpTenantManagementPermissionDefinitionProvider.cs
  3. 11
      modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/GetTenantsInput.cs
  4. 13
      modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/ITenantAppService.cs
  5. 23
      modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/TenantCreateDto.cs
  6. 21
      modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/TenantCreateOrUpdateDtoBase.cs
  7. 13
      modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/TenantDto.cs
  8. 35
      modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/TenantManagementPermissions.cs
  9. 11
      modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/TenantManagementRemoteServiceConsts.cs
  10. 11
      modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/TenantUpdateDto.cs
  11. 15
      modules/tenant-management/src/Volo.Abp.TenantManagement.Application/Volo/Abp/TenantManagement/AbpTenantManagementApplicationAutoMapperProfile.cs
  12. 25
      modules/tenant-management/src/Volo.Abp.TenantManagement.Application/Volo/Abp/TenantManagement/AbpTenantManagementApplicationModule.cs
  13. 217
      modules/tenant-management/src/Volo.Abp.TenantManagement.Application/Volo/Abp/TenantManagement/TenantAppService.cs
  14. 15
      modules/tenant-management/src/Volo.Abp.TenantManagement.Application/Volo/Abp/TenantManagement/TenantManagementAppServiceBase.cs
  15. 15
      modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor.Server/AbpTenantManagementBlazorServerModule.cs
  16. 17
      modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor.WebAssembly/AbpTenantManagementBlazorWebAssemblyModule.cs
  17. 13
      modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/AbpTenantManagementBlazorAutoMapperProfile.cs
  18. 73
      modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/AbpTenantManagementBlazorModule.cs
  19. 43
      modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Navigation/TenantManagementBlazorMenuContributor.cs
  20. 11
      modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Navigation/TenantManagementMenuNames.cs
  21. 111
      modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Pages/TenantManagement/TenantManagement.razor.cs
  22. 21
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/ObjectExtending/TenantManagementModuleExtensionConfiguration.cs
  23. 23
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/ObjectExtending/TenantManagementModuleExtensionConfigurationDictionaryExtensions.cs
  24. 17
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/ObjectExtending/TenantManagementModuleExtensionConsts.cs
  25. 33
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/AbpTenantManagementDomainSharedModule.cs
  26. 11
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/AbpTenantManagementResource.cs
  27. 25
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/TenantConnectionStringConsts.cs
  28. 15
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/TenantConsts.cs
  29. 13
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/TenantEto.cs
  30. 13
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/AbpTenantManagementDbProperties.cs
  31. 37
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/AbpTenantManagementDomainMappingProfile.cs
  32. 61
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/AbpTenantManagementDomainModule.cs
  33. 13
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantManager.cs
  34. 55
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantRepository.cs
  35. 105
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs
  36. 45
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantCacheItem.cs
  37. 25
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantCacheItemInvalidator.cs
  38. 49
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantConnectionString.cs
  39. 55
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs
  40. 191
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs
  41. 59
      modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs
  42. 19
      modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementEntityFrameworkCoreModule.cs
  43. 137
      modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs
  44. 15
      modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/ITenantManagementDbContext.cs
  45. 31
      modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/TenantManagementDbContext.cs
  46. 21
      modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/TenantManagementEfCoreQueryableExtensions.cs
  47. 7
      modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi.Client/ClientProxies/TenantClientProxy.cs
  48. 31
      modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi.Client/Volo/Abp/TenantManagement/AbpTenantManagementHttpApiClientModule.cs
  49. 47
      modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi/Volo/Abp/TenantManagement/AbpTenantManagementHttpApiModule.cs
  50. 117
      modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi/Volo/Abp/TenantManagement/TenantController.cs
  51. 23
      modules/tenant-management/src/Volo.Abp.TenantManagement.Installer/Volo/Abp/TenantManagement/AbpTenantManagementInstallerModule.cs
  52. 29
      modules/tenant-management/src/Volo.Abp.TenantManagement.Installer/Volo/Abp/TenantManagement/TenantManagementInstallerPipelineBuilder.cs
  53. 23
      modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/AbpTenantManagementMongoDbContextExtensions.cs
  54. 25
      modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/AbpTenantManagementMongoDbModule.cs
  55. 13
      modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/ITenantManagementMongoDbContext.cs
  56. 107
      modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs
  57. 21
      modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/TenantManagementMongoDbContext.cs
  58. 25
      modules/tenant-management/src/Volo.Abp.TenantManagement.Web/AbpTenantManagementWebAutoMapperProfile.cs
  59. 149
      modules/tenant-management/src/Volo.Abp.TenantManagement.Web/AbpTenantManagementWebModule.cs
  60. 27
      modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Navigation/AbpTenantManagementWebMainMenuContributor.cs
  61. 11
      modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Navigation/TenantManagementMenuNames.cs
  62. 89
      modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/CreateModal.cshtml.cs
  63. 71
      modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/EditModal.cshtml.cs
  64. 21
      modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.cshtml.cs
  65. 13
      modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/TenantManagementPageModel.cs
  66. 23
      modules/tenant-management/test/Volo.Abp.TenantManagement.Application.Tests/Volo/Abp/TenantManagement/AbpTenantManagementApplicationTestBase.cs
  67. 17
      modules/tenant-management/test/Volo.Abp.TenantManagement.Application.Tests/Volo/Abp/TenantManagement/AbpTenantManagementApplicationTestModule.cs
  68. 173
      modules/tenant-management/test/Volo.Abp.TenantManagement.Application.Tests/Volo/Abp/TenantManagement/TenantAppService_Tests.cs
  69. 13
      modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/AbpSettingManagementDomainTestModule.cs
  70. 7
      modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/AbpTenantManagementDomainTestBase.cs
  71. 45
      modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/Localization_Tests.cs
  72. 111
      modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantCacheItemInvalidator_Tests.cs
  73. 23
      modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantConnectionString_Tests.cs
  74. 87
      modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantManager_Tests.cs
  75. 47
      modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantStore_Tests.cs
  76. 45
      modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/Tenant_Tests.cs
  77. 55
      modules/tenant-management/test/Volo.Abp.TenantManagement.EntityFrameworkCore.Tests/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementEntityFrameworkCoreTestModule.cs
  78. 17
      modules/tenant-management/test/Volo.Abp.TenantManagement.EntityFrameworkCore.Tests/Volo/Abp/TenantManagement/EntityFrameworkCore/LazyLoad_Tests.cs
  79. 7
      modules/tenant-management/test/Volo.Abp.TenantManagement.EntityFrameworkCore.Tests/Volo/Abp/TenantManagement/EntityFrameworkCore/TenantRepository_Tests.cs
  80. 33
      modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/AbpTenantManagementMongoDbTestModule.cs
  81. 27
      modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoDbFixture.cs
  82. 13
      modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoTestCollection.cs
  83. 9
      modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/TenantRepository_Tests.cs
  84. 35
      modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/AbpTenantManagementTestBaseModule.cs
  85. 51
      modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/AbpTenantManagementTestDataBuilder.cs
  86. 37
      modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/LazyLoad_Tests.cs
  87. 13
      modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/TenantManagementTestBase.cs
  88. 91
      modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/TenantRepository_Tests.cs

45
modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/AbpTenantManagementApplicationContractsModule.cs

@ -5,30 +5,29 @@ using Volo.Abp.ObjectExtending;
using Volo.Abp.ObjectExtending.Modularity; using Volo.Abp.ObjectExtending.Modularity;
using Volo.Abp.Threading; using Volo.Abp.Threading;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
[DependsOn(
typeof(AbpDddApplicationContractsModule),
typeof(AbpTenantManagementDomainSharedModule),
typeof(AbpAuthorizationAbstractionsModule)
)]
public class AbpTenantManagementApplicationContractsModule : AbpModule
{ {
[DependsOn( private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
typeof(AbpDddApplicationContractsModule),
typeof(AbpTenantManagementDomainSharedModule),
typeof(AbpAuthorizationAbstractionsModule)
)]
public class AbpTenantManagementApplicationContractsModule : AbpModule
{
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
public override void PostConfigureServices(ServiceConfigurationContext context) public override void PostConfigureServices(ServiceConfigurationContext context)
{
OneTimeRunner.Run(() =>
{ {
OneTimeRunner.Run(() => ModuleExtensionConfigurationHelper
{ .ApplyEntityConfigurationToApi(
ModuleExtensionConfigurationHelper TenantManagementModuleExtensionConsts.ModuleName,
.ApplyEntityConfigurationToApi( TenantManagementModuleExtensionConsts.EntityNames.Tenant,
TenantManagementModuleExtensionConsts.ModuleName, getApiTypes: new[] { typeof(TenantDto) },
TenantManagementModuleExtensionConsts.EntityNames.Tenant, createApiTypes: new[] { typeof(TenantCreateDto) },
getApiTypes: new[] { typeof(TenantDto) }, updateApiTypes: new[] { typeof(TenantUpdateDto) }
createApiTypes: new[] { typeof(TenantCreateDto) }, );
updateApiTypes: new[] { typeof(TenantUpdateDto) } });
);
});
}
} }
} }

31
modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/AbpTenantManagementPermissionDefinitionProvider.cs

@ -3,25 +3,24 @@ using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.TenantManagement.Localization; using Volo.Abp.TenantManagement.Localization;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class AbpTenantManagementPermissionDefinitionProvider : PermissionDefinitionProvider
{ {
public class AbpTenantManagementPermissionDefinitionProvider : PermissionDefinitionProvider public override void Define(IPermissionDefinitionContext context)
{ {
public override void Define(IPermissionDefinitionContext context) var tenantManagementGroup = context.AddGroup(TenantManagementPermissions.GroupName, L("Permission:TenantManagement"));
{
var tenantManagementGroup = context.AddGroup(TenantManagementPermissions.GroupName, L("Permission:TenantManagement"));
var tenantsPermission = tenantManagementGroup.AddPermission(TenantManagementPermissions.Tenants.Default, L("Permission:TenantManagement"), multiTenancySide: MultiTenancySides.Host); var tenantsPermission = tenantManagementGroup.AddPermission(TenantManagementPermissions.Tenants.Default, L("Permission:TenantManagement"), multiTenancySide: MultiTenancySides.Host);
tenantsPermission.AddChild(TenantManagementPermissions.Tenants.Create, L("Permission:Create"), multiTenancySide: MultiTenancySides.Host); tenantsPermission.AddChild(TenantManagementPermissions.Tenants.Create, L("Permission:Create"), multiTenancySide: MultiTenancySides.Host);
tenantsPermission.AddChild(TenantManagementPermissions.Tenants.Update, L("Permission:Edit"), multiTenancySide: MultiTenancySides.Host); tenantsPermission.AddChild(TenantManagementPermissions.Tenants.Update, L("Permission:Edit"), multiTenancySide: MultiTenancySides.Host);
tenantsPermission.AddChild(TenantManagementPermissions.Tenants.Delete, L("Permission:Delete"), multiTenancySide: MultiTenancySides.Host); tenantsPermission.AddChild(TenantManagementPermissions.Tenants.Delete, L("Permission:Delete"), multiTenancySide: MultiTenancySides.Host);
tenantsPermission.AddChild(TenantManagementPermissions.Tenants.ManageFeatures, L("Permission:ManageFeatures"), multiTenancySide: MultiTenancySides.Host); tenantsPermission.AddChild(TenantManagementPermissions.Tenants.ManageFeatures, L("Permission:ManageFeatures"), multiTenancySide: MultiTenancySides.Host);
tenantsPermission.AddChild(TenantManagementPermissions.Tenants.ManageConnectionStrings, L("Permission:ManageConnectionStrings"), multiTenancySide: MultiTenancySides.Host); tenantsPermission.AddChild(TenantManagementPermissions.Tenants.ManageConnectionStrings, L("Permission:ManageConnectionStrings"), multiTenancySide: MultiTenancySides.Host);
} }
private static LocalizableString L(string name) private static LocalizableString L(string name)
{ {
return LocalizableString.Create<AbpTenantManagementResource>(name); return LocalizableString.Create<AbpTenantManagementResource>(name);
}
} }
} }

11
modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/GetTenantsInput.cs

@ -1,9 +1,8 @@
using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Dtos;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class GetTenantsInput : PagedAndSortedResultRequestDto
{ {
public class GetTenantsInput : PagedAndSortedResultRequestDto public string Filter { get; set; }
{ }
public string Filter { get; set; }
}
}

13
modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/ITenantAppService.cs

@ -2,14 +2,13 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public interface ITenantAppService : ICrudAppService<TenantDto, Guid, GetTenantsInput, TenantCreateDto, TenantUpdateDto>
{ {
public interface ITenantAppService : ICrudAppService<TenantDto, Guid, GetTenantsInput, TenantCreateDto, TenantUpdateDto> Task<string> GetDefaultConnectionStringAsync(Guid id);
{
Task<string> GetDefaultConnectionStringAsync(Guid id);
Task UpdateDefaultConnectionStringAsync(Guid id, string defaultConnectionString); Task UpdateDefaultConnectionStringAsync(Guid id, string defaultConnectionString);
Task DeleteDefaultConnectionStringAsync(Guid id); Task DeleteDefaultConnectionStringAsync(Guid id);
}
} }

23
modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/TenantCreateDto.cs

@ -1,16 +1,15 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class TenantCreateDto : TenantCreateOrUpdateDtoBase
{ {
public class TenantCreateDto : TenantCreateOrUpdateDtoBase [Required]
{ [EmailAddress]
[Required] [MaxLength(256)]
[EmailAddress] public virtual string AdminEmailAddress { get; set; }
[MaxLength(256)]
public virtual string AdminEmailAddress { get; set; }
[Required] [Required]
[MaxLength(128)] [MaxLength(128)]
public virtual string AdminPassword { get; set; } public virtual string AdminPassword { get; set; }
} }
}

21
modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/TenantCreateOrUpdateDtoBase.cs

@ -2,18 +2,17 @@
using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectExtending;
using Volo.Abp.Validation; using Volo.Abp.Validation;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public abstract class TenantCreateOrUpdateDtoBase : ExtensibleObject
{ {
public abstract class TenantCreateOrUpdateDtoBase : ExtensibleObject [Required]
{ [DynamicStringLength(typeof(TenantConsts), nameof(TenantConsts.MaxNameLength))]
[Required] [Display(Name = "TenantName")]
[DynamicStringLength(typeof(TenantConsts), nameof(TenantConsts.MaxNameLength))] public string Name { get; set; }
[Display(Name = "TenantName")]
public string Name { get; set; }
public TenantCreateOrUpdateDtoBase() : base(false) public TenantCreateOrUpdateDtoBase() : base(false)
{ {
}
} }
} }

13
modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/TenantDto.cs

@ -2,12 +2,11 @@
using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class TenantDto : ExtensibleEntityDto<Guid>, IHasConcurrencyStamp
{ {
public class TenantDto : ExtensibleEntityDto<Guid>, IHasConcurrencyStamp public string Name { get; set; }
{
public string Name { get; set; }
public string ConcurrencyStamp { get; set; } public string ConcurrencyStamp { get; set; }
} }
}

35
modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/TenantManagementPermissions.cs

@ -1,24 +1,23 @@
using Volo.Abp.Reflection; using Volo.Abp.Reflection;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public static class TenantManagementPermissions
{ {
public static class TenantManagementPermissions public const string GroupName = "AbpTenantManagement";
{
public const string GroupName = "AbpTenantManagement";
public static class Tenants public static class Tenants
{ {
public const string Default = GroupName + ".Tenants"; public const string Default = GroupName + ".Tenants";
public const string Create = Default + ".Create"; public const string Create = Default + ".Create";
public const string Update = Default + ".Update"; public const string Update = Default + ".Update";
public const string Delete = Default + ".Delete"; public const string Delete = Default + ".Delete";
public const string ManageFeatures = Default + ".ManageFeatures"; public const string ManageFeatures = Default + ".ManageFeatures";
public const string ManageConnectionStrings = Default + ".ManageConnectionStrings"; public const string ManageConnectionStrings = Default + ".ManageConnectionStrings";
} }
public static string[] GetAll() public static string[] GetAll()
{ {
return ReflectionHelper.GetPublicConstantsRecursively(typeof(TenantManagementPermissions)); return ReflectionHelper.GetPublicConstantsRecursively(typeof(TenantManagementPermissions));
}
} }
} }

11
modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/TenantManagementRemoteServiceConsts.cs

@ -1,9 +1,8 @@
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class TenantManagementRemoteServiceConsts
{ {
public class TenantManagementRemoteServiceConsts public const string RemoteServiceName = "AbpTenantManagement";
{
public const string RemoteServiceName = "AbpTenantManagement";
public const string ModuleName = "multi-tenancy"; public const string ModuleName = "multi-tenancy";
}
} }

11
modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/TenantUpdateDto.cs

@ -1,9 +1,8 @@
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class TenantUpdateDto : TenantCreateOrUpdateDtoBase, IHasConcurrencyStamp
{ {
public class TenantUpdateDto : TenantCreateOrUpdateDtoBase, IHasConcurrencyStamp public string ConcurrencyStamp { get; set; }
{ }
public string ConcurrencyStamp { get; set; }
}
}

15
modules/tenant-management/src/Volo.Abp.TenantManagement.Application/Volo/Abp/TenantManagement/AbpTenantManagementApplicationAutoMapperProfile.cs

@ -1,13 +1,12 @@
using AutoMapper; using AutoMapper;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class AbpTenantManagementApplicationAutoMapperProfile : Profile
{ {
public class AbpTenantManagementApplicationAutoMapperProfile : Profile public AbpTenantManagementApplicationAutoMapperProfile()
{ {
public AbpTenantManagementApplicationAutoMapperProfile() CreateMap<Tenant, TenantDto>()
{ .MapExtraProperties();
CreateMap<Tenant, TenantDto>()
.MapExtraProperties();
}
} }
} }

25
modules/tenant-management/src/Volo.Abp.TenantManagement.Application/Volo/Abp/TenantManagement/AbpTenantManagementApplicationModule.cs

@ -3,20 +3,19 @@ using Volo.Abp.Application;
using Volo.Abp.AutoMapper; using Volo.Abp.AutoMapper;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
[DependsOn(typeof(AbpTenantManagementDomainModule))]
[DependsOn(typeof(AbpTenantManagementApplicationContractsModule))]
[DependsOn(typeof(AbpDddApplicationModule))]
public class AbpTenantManagementApplicationModule : AbpModule
{ {
[DependsOn(typeof(AbpTenantManagementDomainModule))] public override void ConfigureServices(ServiceConfigurationContext context)
[DependsOn(typeof(AbpTenantManagementApplicationContractsModule))]
[DependsOn(typeof(AbpDddApplicationModule))]
public class AbpTenantManagementApplicationModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) context.Services.AddAutoMapperObjectMapper<AbpTenantManagementApplicationModule>();
Configure<AbpAutoMapperOptions>(options =>
{ {
context.Services.AddAutoMapperObjectMapper<AbpTenantManagementApplicationModule>(); options.AddProfile<AbpTenantManagementApplicationAutoMapperProfile>(validate: true);
Configure<AbpAutoMapperOptions>(options => });
{
options.AddProfile<AbpTenantManagementApplicationAutoMapperProfile>(validate: true);
});
}
} }
} }

217
modules/tenant-management/src/Volo.Abp.TenantManagement.Application/Volo/Abp/TenantManagement/TenantAppService.cs

@ -8,140 +8,139 @@ using Volo.Abp.EventBus.Distributed;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectExtending;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
[Authorize(TenantManagementPermissions.Tenants.Default)]
public class TenantAppService : TenantManagementAppServiceBase, ITenantAppService
{ {
[Authorize(TenantManagementPermissions.Tenants.Default)] protected IDataSeeder DataSeeder { get; }
public class TenantAppService : TenantManagementAppServiceBase, ITenantAppService protected ITenantRepository TenantRepository { get; }
protected ITenantManager TenantManager { get; }
protected IDistributedEventBus DistributedEventBus { get; }
public TenantAppService(
ITenantRepository tenantRepository,
ITenantManager tenantManager,
IDataSeeder dataSeeder,
IDistributedEventBus distributedEventBus)
{ {
protected IDataSeeder DataSeeder { get; } DataSeeder = dataSeeder;
protected ITenantRepository TenantRepository { get; } TenantRepository = tenantRepository;
protected ITenantManager TenantManager { get; } TenantManager = tenantManager;
protected IDistributedEventBus DistributedEventBus { get; } DistributedEventBus = distributedEventBus;
}
public TenantAppService(
ITenantRepository tenantRepository,
ITenantManager tenantManager,
IDataSeeder dataSeeder,
IDistributedEventBus distributedEventBus)
{
DataSeeder = dataSeeder;
TenantRepository = tenantRepository;
TenantManager = tenantManager;
DistributedEventBus = distributedEventBus;
}
public virtual async Task<TenantDto> GetAsync(Guid id) public virtual async Task<TenantDto> GetAsync(Guid id)
{ {
return ObjectMapper.Map<Tenant, TenantDto>( return ObjectMapper.Map<Tenant, TenantDto>(
await TenantRepository.GetAsync(id) await TenantRepository.GetAsync(id)
); );
} }
public virtual async Task<PagedResultDto<TenantDto>> GetListAsync(GetTenantsInput input) public virtual async Task<PagedResultDto<TenantDto>> GetListAsync(GetTenantsInput input)
{
if (input.Sorting.IsNullOrWhiteSpace())
{ {
if (input.Sorting.IsNullOrWhiteSpace()) input.Sorting = nameof(Tenant.Name);
{
input.Sorting = nameof(Tenant.Name);
}
var count = await TenantRepository.GetCountAsync(input.Filter);
var list = await TenantRepository.GetListAsync(
input.Sorting,
input.MaxResultCount,
input.SkipCount,
input.Filter
);
return new PagedResultDto<TenantDto>(
count,
ObjectMapper.Map<List<Tenant>, List<TenantDto>>(list)
);
} }
[Authorize(TenantManagementPermissions.Tenants.Create)] var count = await TenantRepository.GetCountAsync(input.Filter);
public virtual async Task<TenantDto> CreateAsync(TenantCreateDto input) var list = await TenantRepository.GetListAsync(
{ input.Sorting,
var tenant = await TenantManager.CreateAsync(input.Name); input.MaxResultCount,
input.MapExtraPropertiesTo(tenant); input.SkipCount,
input.Filter
);
return new PagedResultDto<TenantDto>(
count,
ObjectMapper.Map<List<Tenant>, List<TenantDto>>(list)
);
}
await TenantRepository.InsertAsync(tenant); [Authorize(TenantManagementPermissions.Tenants.Create)]
public virtual async Task<TenantDto> CreateAsync(TenantCreateDto input)
{
var tenant = await TenantManager.CreateAsync(input.Name);
input.MapExtraPropertiesTo(tenant);
await CurrentUnitOfWork.SaveChangesAsync(); await TenantRepository.InsertAsync(tenant);
await DistributedEventBus.PublishAsync( await CurrentUnitOfWork.SaveChangesAsync();
new TenantCreatedEto
await DistributedEventBus.PublishAsync(
new TenantCreatedEto
{
Id = tenant.Id,
Name = tenant.Name,
Properties =
{ {
Id = tenant.Id,
Name = tenant.Name,
Properties =
{
{ "AdminEmail", input.AdminEmailAddress }, { "AdminEmail", input.AdminEmailAddress },
{ "AdminPassword", input.AdminPassword } { "AdminPassword", input.AdminPassword }
} }
}); });
using (CurrentTenant.Change(tenant.Id, tenant.Name)) using (CurrentTenant.Change(tenant.Id, tenant.Name))
{
//TODO: Handle database creation?
// TODO: Seeder might be triggered via event handler.
await DataSeeder.SeedAsync(
new DataSeedContext(tenant.Id)
.WithProperty("AdminEmail", input.AdminEmailAddress)
.WithProperty("AdminPassword", input.AdminPassword)
);
}
return ObjectMapper.Map<Tenant, TenantDto>(tenant);
}
[Authorize(TenantManagementPermissions.Tenants.Update)]
public virtual async Task<TenantDto> UpdateAsync(Guid id, TenantUpdateDto input)
{ {
var tenant = await TenantRepository.GetAsync(id); //TODO: Handle database creation?
// TODO: Seeder might be triggered via event handler.
await DataSeeder.SeedAsync(
new DataSeedContext(tenant.Id)
.WithProperty("AdminEmail", input.AdminEmailAddress)
.WithProperty("AdminPassword", input.AdminPassword)
);
}
await TenantManager.ChangeNameAsync(tenant, input.Name); return ObjectMapper.Map<Tenant, TenantDto>(tenant);
}
tenant.SetConcurrencyStampIfNotNull(input.ConcurrencyStamp); [Authorize(TenantManagementPermissions.Tenants.Update)]
input.MapExtraPropertiesTo(tenant); public virtual async Task<TenantDto> UpdateAsync(Guid id, TenantUpdateDto input)
{
var tenant = await TenantRepository.GetAsync(id);
await TenantRepository.UpdateAsync(tenant); await TenantManager.ChangeNameAsync(tenant, input.Name);
return ObjectMapper.Map<Tenant, TenantDto>(tenant); tenant.SetConcurrencyStampIfNotNull(input.ConcurrencyStamp);
} input.MapExtraPropertiesTo(tenant);
[Authorize(TenantManagementPermissions.Tenants.Delete)] await TenantRepository.UpdateAsync(tenant);
public virtual async Task DeleteAsync(Guid id)
{
var tenant = await TenantRepository.FindAsync(id);
if (tenant == null)
{
return;
}
await TenantRepository.DeleteAsync(tenant); return ObjectMapper.Map<Tenant, TenantDto>(tenant);
} }
[Authorize(TenantManagementPermissions.Tenants.ManageConnectionStrings)] [Authorize(TenantManagementPermissions.Tenants.Delete)]
public virtual async Task<string> GetDefaultConnectionStringAsync(Guid id) public virtual async Task DeleteAsync(Guid id)
{
var tenant = await TenantRepository.FindAsync(id);
if (tenant == null)
{ {
var tenant = await TenantRepository.GetAsync(id); return;
return tenant?.FindDefaultConnectionString();
} }
[Authorize(TenantManagementPermissions.Tenants.ManageConnectionStrings)] await TenantRepository.DeleteAsync(tenant);
public virtual async Task UpdateDefaultConnectionStringAsync(Guid id, string defaultConnectionString) }
{
var tenant = await TenantRepository.GetAsync(id);
tenant.SetDefaultConnectionString(defaultConnectionString);
await TenantRepository.UpdateAsync(tenant);
}
[Authorize(TenantManagementPermissions.Tenants.ManageConnectionStrings)] [Authorize(TenantManagementPermissions.Tenants.ManageConnectionStrings)]
public virtual async Task DeleteDefaultConnectionStringAsync(Guid id) public virtual async Task<string> GetDefaultConnectionStringAsync(Guid id)
{ {
var tenant = await TenantRepository.GetAsync(id); var tenant = await TenantRepository.GetAsync(id);
tenant.RemoveDefaultConnectionString(); return tenant?.FindDefaultConnectionString();
await TenantRepository.UpdateAsync(tenant); }
}
[Authorize(TenantManagementPermissions.Tenants.ManageConnectionStrings)]
public virtual async Task UpdateDefaultConnectionStringAsync(Guid id, string defaultConnectionString)
{
var tenant = await TenantRepository.GetAsync(id);
tenant.SetDefaultConnectionString(defaultConnectionString);
await TenantRepository.UpdateAsync(tenant);
}
[Authorize(TenantManagementPermissions.Tenants.ManageConnectionStrings)]
public virtual async Task DeleteDefaultConnectionStringAsync(Guid id)
{
var tenant = await TenantRepository.GetAsync(id);
tenant.RemoveDefaultConnectionString();
await TenantRepository.UpdateAsync(tenant);
} }
} }

15
modules/tenant-management/src/Volo.Abp.TenantManagement.Application/Volo/Abp/TenantManagement/TenantManagementAppServiceBase.cs

@ -1,14 +1,13 @@
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
using Volo.Abp.TenantManagement.Localization; using Volo.Abp.TenantManagement.Localization;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public abstract class TenantManagementAppServiceBase : ApplicationService
{ {
public abstract class TenantManagementAppServiceBase : ApplicationService protected TenantManagementAppServiceBase()
{ {
protected TenantManagementAppServiceBase() ObjectMapperContext = typeof(AbpTenantManagementApplicationModule);
{ LocalizationResource = typeof(AbpTenantManagementResource);
ObjectMapperContext = typeof(AbpTenantManagementApplicationModule);
LocalizationResource = typeof(AbpTenantManagementResource);
}
} }
} }

15
modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor.Server/AbpTenantManagementBlazorServerModule.cs

@ -2,14 +2,13 @@
using Volo.Abp.FeatureManagement.Blazor.Server; using Volo.Abp.FeatureManagement.Blazor.Server;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace Volo.Abp.TenantManagement.Blazor.Server namespace Volo.Abp.TenantManagement.Blazor.Server;
[DependsOn(
typeof(AbpTenantManagementBlazorModule),
typeof(AbpFeatureManagementBlazorServerModule)
)]
public class AbpTenantManagementBlazorServerModule : AbpModule
{ {
[DependsOn(
typeof(AbpTenantManagementBlazorModule),
typeof(AbpFeatureManagementBlazorServerModule)
)]
public class AbpTenantManagementBlazorServerModule : AbpModule
{
}
} }

17
modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor.WebAssembly/AbpTenantManagementBlazorWebAssemblyModule.cs

@ -2,15 +2,14 @@
using Volo.Abp.FeatureManagement.Blazor.WebAssembly; using Volo.Abp.FeatureManagement.Blazor.WebAssembly;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace Volo.Abp.TenantManagement.Blazor.WebAssembly namespace Volo.Abp.TenantManagement.Blazor.WebAssembly;
[DependsOn(
typeof(AbpTenantManagementBlazorModule),
typeof(AbpFeatureManagementBlazorWebAssemblyModule),
typeof(AbpTenantManagementHttpApiClientModule)
)]
public class AbpTenantManagementBlazorWebAssemblyModule : AbpModule
{ {
[DependsOn(
typeof(AbpTenantManagementBlazorModule),
typeof(AbpFeatureManagementBlazorWebAssemblyModule),
typeof(AbpTenantManagementHttpApiClientModule)
)]
public class AbpTenantManagementBlazorWebAssemblyModule : AbpModule
{
}
} }

13
modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/AbpTenantManagementBlazorAutoMapperProfile.cs

@ -1,13 +1,12 @@
using AutoMapper; using AutoMapper;
namespace Volo.Abp.TenantManagement.Blazor namespace Volo.Abp.TenantManagement.Blazor;
public class AbpTenantManagementBlazorAutoMapperProfile : Profile
{ {
public class AbpTenantManagementBlazorAutoMapperProfile : Profile public AbpTenantManagementBlazorAutoMapperProfile()
{ {
public AbpTenantManagementBlazorAutoMapperProfile() CreateMap<TenantDto, TenantUpdateDto>()
{ .MapExtraProperties();
CreateMap<TenantDto, TenantUpdateDto>()
.MapExtraProperties();
}
} }
} }

73
modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/AbpTenantManagementBlazorModule.cs

@ -9,49 +9,48 @@ using Volo.Abp.TenantManagement.Blazor.Navigation;
using Volo.Abp.Threading; using Volo.Abp.Threading;
using Volo.Abp.UI.Navigation; using Volo.Abp.UI.Navigation;
namespace Volo.Abp.TenantManagement.Blazor namespace Volo.Abp.TenantManagement.Blazor;
[DependsOn(
typeof(AbpAutoMapperModule),
typeof(AbpTenantManagementApplicationContractsModule),
typeof(AbpFeatureManagementBlazorModule)
)]
public class AbpTenantManagementBlazorModule : AbpModule
{ {
[DependsOn( private static readonly OneTimeRunner OneTimeRunner = new();
typeof(AbpAutoMapperModule),
typeof(AbpTenantManagementApplicationContractsModule), public override void ConfigureServices(ServiceConfigurationContext context)
typeof(AbpFeatureManagementBlazorModule)
)]
public class AbpTenantManagementBlazorModule : AbpModule
{ {
private static readonly OneTimeRunner OneTimeRunner = new(); context.Services.AddAutoMapperObjectMapper<AbpTenantManagementBlazorModule>();
public override void ConfigureServices(ServiceConfigurationContext context) Configure<AbpAutoMapperOptions>(options =>
{ {
context.Services.AddAutoMapperObjectMapper<AbpTenantManagementBlazorModule>(); options.AddProfile<AbpTenantManagementBlazorAutoMapperProfile>(validate: true);
});
Configure<AbpAutoMapperOptions>(options => Configure<AbpNavigationOptions>(options =>
{ {
options.AddProfile<AbpTenantManagementBlazorAutoMapperProfile>(validate: true); options.MenuContributors.Add(new TenantManagementBlazorMenuContributor());
}); });
Configure<AbpNavigationOptions>(options => Configure<AbpRouterOptions>(options =>
{ {
options.MenuContributors.Add(new TenantManagementBlazorMenuContributor()); options.AdditionalAssemblies.Add(typeof(AbpTenantManagementBlazorModule).Assembly);
}); });
}
Configure<AbpRouterOptions>(options => public override void PostConfigureServices(ServiceConfigurationContext context)
{ {
options.AdditionalAssemblies.Add(typeof(AbpTenantManagementBlazorModule).Assembly); OneTimeRunner.Run(() =>
});
}
public override void PostConfigureServices(ServiceConfigurationContext context)
{ {
OneTimeRunner.Run(() => ModuleExtensionConfigurationHelper
{ .ApplyEntityConfigurationToUi(
ModuleExtensionConfigurationHelper TenantManagementModuleExtensionConsts.ModuleName,
.ApplyEntityConfigurationToUi( TenantManagementModuleExtensionConsts.EntityNames.Tenant,
TenantManagementModuleExtensionConsts.ModuleName, createFormTypes: new[] { typeof(TenantCreateDto) },
TenantManagementModuleExtensionConsts.EntityNames.Tenant, editFormTypes: new[] { typeof(TenantUpdateDto) }
createFormTypes: new[] { typeof(TenantCreateDto) }, );
editFormTypes: new[] { typeof(TenantUpdateDto) } });
);
});
}
} }
} }

43
modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Navigation/TenantManagementBlazorMenuContributor.cs

@ -3,35 +3,34 @@ using Volo.Abp.TenantManagement.Localization;
using Volo.Abp.UI.Navigation; using Volo.Abp.UI.Navigation;
using Volo.Abp.Authorization.Permissions; using Volo.Abp.Authorization.Permissions;
namespace Volo.Abp.TenantManagement.Blazor.Navigation namespace Volo.Abp.TenantManagement.Blazor.Navigation;
public class TenantManagementBlazorMenuContributor : IMenuContributor
{ {
public class TenantManagementBlazorMenuContributor : IMenuContributor public virtual Task ConfigureMenuAsync(MenuConfigurationContext context)
{ {
public virtual Task ConfigureMenuAsync(MenuConfigurationContext context) if (context.Menu.Name != StandardMenus.Main)
{ {
if (context.Menu.Name != StandardMenus.Main) return Task.CompletedTask;
{ }
return Task.CompletedTask;
}
var administrationMenu = context.Menu.GetAdministration(); var administrationMenu = context.Menu.GetAdministration();
var l = context.GetLocalizer<AbpTenantManagementResource>(); var l = context.GetLocalizer<AbpTenantManagementResource>();
var tenantManagementMenuItem = new ApplicationMenuItem( var tenantManagementMenuItem = new ApplicationMenuItem(
TenantManagementMenuNames.GroupName, TenantManagementMenuNames.GroupName,
l["Menu:TenantManagement"], l["Menu:TenantManagement"],
icon: "fa fa-users" icon: "fa fa-users"
); );
administrationMenu.AddItem(tenantManagementMenuItem); administrationMenu.AddItem(tenantManagementMenuItem);
tenantManagementMenuItem.AddItem(new ApplicationMenuItem( tenantManagementMenuItem.AddItem(new ApplicationMenuItem(
TenantManagementMenuNames.Tenants, TenantManagementMenuNames.Tenants,
l["Tenants"], l["Tenants"],
url: "~/tenant-management/tenants" url: "~/tenant-management/tenants"
).RequirePermissions(TenantManagementPermissions.Tenants.Default)); ).RequirePermissions(TenantManagementPermissions.Tenants.Default));
return Task.CompletedTask; return Task.CompletedTask;
}
} }
} }

11
modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Navigation/TenantManagementMenuNames.cs

@ -1,9 +1,8 @@
namespace Volo.Abp.TenantManagement.Blazor.Navigation namespace Volo.Abp.TenantManagement.Blazor.Navigation;
public class TenantManagementMenuNames
{ {
public class TenantManagementMenuNames public const string GroupName = "TenantManagement";
{
public const string GroupName = "TenantManagement";
public const string Tenants = GroupName + ".Tenants"; public const string Tenants = GroupName + ".Tenants";
}
} }

111
modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Pages/TenantManagement/TenantManagement.razor.cs

@ -12,61 +12,61 @@ using Volo.Abp.FeatureManagement.Blazor.Components;
using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectExtending;
using Volo.Abp.TenantManagement.Localization; using Volo.Abp.TenantManagement.Localization;
namespace Volo.Abp.TenantManagement.Blazor.Pages.TenantManagement namespace Volo.Abp.TenantManagement.Blazor.Pages.TenantManagement;
public partial class TenantManagement
{ {
public partial class TenantManagement protected const string FeatureProviderName = "T";
{
protected const string FeatureProviderName = "T";
protected bool HasManageFeaturesPermission; protected bool HasManageFeaturesPermission;
protected string ManageFeaturesPolicyName; protected string ManageFeaturesPolicyName;
protected FeatureManagementModal FeatureManagementModal; protected FeatureManagementModal FeatureManagementModal;
protected PageToolbar Toolbar { get; } = new(); protected PageToolbar Toolbar { get; } = new();
protected List<TableColumn> TenantManagementTableColumns => TableColumns.Get<TenantManagement>(); protected List<TableColumn> TenantManagementTableColumns => TableColumns.Get<TenantManagement>();
public TenantManagement() public TenantManagement()
{ {
LocalizationResource = typeof(AbpTenantManagementResource); LocalizationResource = typeof(AbpTenantManagementResource);
ObjectMapperContext = typeof(AbpTenantManagementBlazorModule); ObjectMapperContext = typeof(AbpTenantManagementBlazorModule);
CreatePolicyName = TenantManagementPermissions.Tenants.Create; CreatePolicyName = TenantManagementPermissions.Tenants.Create;
UpdatePolicyName = TenantManagementPermissions.Tenants.Update; UpdatePolicyName = TenantManagementPermissions.Tenants.Update;
DeletePolicyName = TenantManagementPermissions.Tenants.Delete; DeletePolicyName = TenantManagementPermissions.Tenants.Delete;
ManageFeaturesPolicyName = TenantManagementPermissions.Tenants.ManageFeatures; ManageFeaturesPolicyName = TenantManagementPermissions.Tenants.ManageFeatures;
} }
protected override async Task SetPermissionsAsync() protected override async Task SetPermissionsAsync()
{ {
await base.SetPermissionsAsync(); await base.SetPermissionsAsync();
HasManageFeaturesPermission = await AuthorizationService.IsGrantedAsync(ManageFeaturesPolicyName); HasManageFeaturesPermission = await AuthorizationService.IsGrantedAsync(ManageFeaturesPolicyName);
} }
protected override string GetDeleteConfirmationMessage(TenantDto entity) protected override string GetDeleteConfirmationMessage(TenantDto entity)
{ {
return string.Format(L["TenantDeletionConfirmationMessage"], entity.Name); return string.Format(L["TenantDeletionConfirmationMessage"], entity.Name);
} }
protected override ValueTask SetToolbarItemsAsync() protected override ValueTask SetToolbarItemsAsync()
{ {
Toolbar.AddButton(L["NewTenant"], Toolbar.AddButton(L["NewTenant"],
OpenCreateModalAsync, OpenCreateModalAsync,
IconName.Add, IconName.Add,
requiredPolicyName: CreatePolicyName); requiredPolicyName: CreatePolicyName);
return base.SetToolbarItemsAsync(); return base.SetToolbarItemsAsync();
} }
protected override ValueTask SetEntityActionsAsync() protected override ValueTask SetEntityActionsAsync()
{ {
EntityActions EntityActions
.Get<TenantManagement>() .Get<TenantManagement>()
.AddRange(new EntityAction[] .AddRange(new EntityAction[]
{ {
new EntityAction new EntityAction
{ {
Text = L["Edit"], Text = L["Edit"],
@ -90,16 +90,16 @@ namespace Volo.Abp.TenantManagement.Blazor.Pages.TenantManagement
Clicked = async (data) => await DeleteEntityAsync(data.As<TenantDto>()), Clicked = async (data) => await DeleteEntityAsync(data.As<TenantDto>()),
ConfirmationMessage = (data) => GetDeleteConfirmationMessage(data.As<TenantDto>()) ConfirmationMessage = (data) => GetDeleteConfirmationMessage(data.As<TenantDto>())
} }
}); });
return base.SetEntityActionsAsync(); return base.SetEntityActionsAsync();
} }
protected override ValueTask SetTableColumnsAsync() protected override ValueTask SetTableColumnsAsync()
{ {
TenantManagementTableColumns TenantManagementTableColumns
.AddRange(new TableColumn[] .AddRange(new TableColumn[]
{ {
new TableColumn new TableColumn
{ {
Title = L["Actions"], Title = L["Actions"],
@ -110,13 +110,12 @@ namespace Volo.Abp.TenantManagement.Blazor.Pages.TenantManagement
Title = L["TenantName"], Title = L["TenantName"],
Data = nameof(TenantDto.Name), Data = nameof(TenantDto.Name),
}, },
}); });
TenantManagementTableColumns.AddRange(GetExtensionTableColumns( TenantManagementTableColumns.AddRange(GetExtensionTableColumns(
TenantManagementModuleExtensionConsts.ModuleName, TenantManagementModuleExtensionConsts.ModuleName,
TenantManagementModuleExtensionConsts.EntityNames.Tenant)); TenantManagementModuleExtensionConsts.EntityNames.Tenant));
return base.SetTableColumnsAsync(); return base.SetTableColumnsAsync();
}
} }
} }

21
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/ObjectExtending/TenantManagementModuleExtensionConfiguration.cs

@ -1,17 +1,16 @@
using System; using System;
using Volo.Abp.ObjectExtending.Modularity; using Volo.Abp.ObjectExtending.Modularity;
namespace Volo.Abp.ObjectExtending namespace Volo.Abp.ObjectExtending;
public class TenantManagementModuleExtensionConfiguration : ModuleExtensionConfiguration
{ {
public class TenantManagementModuleExtensionConfiguration : ModuleExtensionConfiguration public TenantManagementModuleExtensionConfiguration ConfigureTenant(
Action<EntityExtensionConfiguration> configureAction)
{ {
public TenantManagementModuleExtensionConfiguration ConfigureTenant( return this.ConfigureEntity(
Action<EntityExtensionConfiguration> configureAction) TenantManagementModuleExtensionConsts.EntityNames.Tenant,
{ configureAction
return this.ConfigureEntity( );
TenantManagementModuleExtensionConsts.EntityNames.Tenant,
configureAction
);
}
} }
} }

23
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/ObjectExtending/TenantManagementModuleExtensionConfigurationDictionaryExtensions.cs

@ -1,18 +1,17 @@
using System; using System;
using Volo.Abp.ObjectExtending.Modularity; using Volo.Abp.ObjectExtending.Modularity;
namespace Volo.Abp.ObjectExtending namespace Volo.Abp.ObjectExtending;
public static class TenantManagementModuleExtensionConfigurationDictionaryExtensions
{ {
public static class TenantManagementModuleExtensionConfigurationDictionaryExtensions public static ModuleExtensionConfigurationDictionary ConfigureTenantManagement(
this ModuleExtensionConfigurationDictionary modules,
Action<TenantManagementModuleExtensionConfiguration> configureAction)
{ {
public static ModuleExtensionConfigurationDictionary ConfigureTenantManagement( return modules.ConfigureModule(
this ModuleExtensionConfigurationDictionary modules, TenantManagementModuleExtensionConsts.ModuleName,
Action<TenantManagementModuleExtensionConfiguration> configureAction) configureAction
{ );
return modules.ConfigureModule(
TenantManagementModuleExtensionConsts.ModuleName,
configureAction
);
}
} }
} }

17
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/ObjectExtending/TenantManagementModuleExtensionConsts.cs

@ -1,12 +1,11 @@
namespace Volo.Abp.ObjectExtending namespace Volo.Abp.ObjectExtending;
public class TenantManagementModuleExtensionConsts
{ {
public class TenantManagementModuleExtensionConsts public const string ModuleName = "TenantManagement";
{
public const string ModuleName = "TenantManagement";
public static class EntityNames public static class EntityNames
{ {
public const string Tenant = "Tenant"; public const string Tenant = "Tenant";
}
} }
} }

33
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/AbpTenantManagementDomainSharedModule.cs

@ -5,26 +5,25 @@ using Volo.Abp.Validation;
using Volo.Abp.Validation.Localization; using Volo.Abp.Validation.Localization;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
[DependsOn(typeof(AbpValidationModule))]
public class AbpTenantManagementDomainSharedModule : AbpModule
{ {
[DependsOn(typeof(AbpValidationModule))] public override void ConfigureServices(ServiceConfigurationContext context)
public class AbpTenantManagementDomainSharedModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) Configure<AbpVirtualFileSystemOptions>(options =>
{ {
Configure<AbpVirtualFileSystemOptions>(options => options.FileSets.AddEmbedded<AbpTenantManagementDomainSharedModule>();
{ });
options.FileSets.AddEmbedded<AbpTenantManagementDomainSharedModule>();
});
Configure<AbpLocalizationOptions>(options => Configure<AbpLocalizationOptions>(options =>
{ {
options.Resources options.Resources
.Add<AbpTenantManagementResource>("en") .Add<AbpTenantManagementResource>("en")
.AddBaseTypes( .AddBaseTypes(
typeof(AbpValidationResource) typeof(AbpValidationResource)
).AddVirtualJson("/Volo/Abp/TenantManagement/Localization/Resources"); ).AddVirtualJson("/Volo/Abp/TenantManagement/Localization/Resources");
}); });
}
} }
} }

11
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/AbpTenantManagementResource.cs

@ -1,10 +1,9 @@
using Volo.Abp.Localization; using Volo.Abp.Localization;
namespace Volo.Abp.TenantManagement.Localization namespace Volo.Abp.TenantManagement.Localization;
[LocalizationResourceName("AbpTenantManagement")]
public class AbpTenantManagementResource
{ {
[LocalizationResourceName("AbpTenantManagement")]
public class AbpTenantManagementResource
{
}
} }

25
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/TenantConnectionStringConsts.cs

@ -1,15 +1,14 @@
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public static class TenantConnectionStringConsts
{ {
public static class TenantConnectionStringConsts /// <summary>
{ /// Default value: 64
/// <summary> /// </summary>
/// Default value: 64 public static int MaxNameLength { get; set; } = 64;
/// </summary>
public static int MaxNameLength { get; set; } = 64;
/// <summary> /// <summary>
/// Default value: 1024 /// Default value: 1024
/// </summary> /// </summary>
public static int MaxValueLength { get; set; } = 1024; public static int MaxValueLength { get; set; } = 1024;
} }
}

15
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/TenantConsts.cs

@ -1,10 +1,9 @@
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public static class TenantConsts
{ {
public static class TenantConsts /// <summary>
{ /// Default value: 64
/// <summary> /// </summary>
/// Default value: 64 public static int MaxNameLength { get; set; } = 64;
/// </summary>
public static int MaxNameLength { get; set; } = 64;
}
} }

13
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/TenantEto.cs

@ -1,12 +1,11 @@
using System; using System;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
[Serializable]
public class TenantEto
{ {
[Serializable] public Guid Id { get; set; }
public class TenantEto
{
public Guid Id { get; set; }
public string Name { get; set; } public string Name { get; set; }
}
} }

13
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/AbpTenantManagementDbProperties.cs

@ -1,13 +1,12 @@
using Volo.Abp.Data; using Volo.Abp.Data;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public static class AbpTenantManagementDbProperties
{ {
public static class AbpTenantManagementDbProperties public static string DbTablePrefix { get; set; } = AbpCommonDbProperties.DbTablePrefix;
{
public static string DbTablePrefix { get; set; } = AbpCommonDbProperties.DbTablePrefix;
public static string DbSchema { get; set; } = AbpCommonDbProperties.DbSchema; public static string DbSchema { get; set; } = AbpCommonDbProperties.DbSchema;
public const string ConnectionStringName = "AbpTenantManagement"; public const string ConnectionStringName = "AbpTenantManagement";
}
} }

37
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/AbpTenantManagementDomainMappingProfile.cs

@ -2,30 +2,29 @@
using Volo.Abp.Data; using Volo.Abp.Data;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class AbpTenantManagementDomainMappingProfile : Profile
{ {
public class AbpTenantManagementDomainMappingProfile : Profile public AbpTenantManagementDomainMappingProfile()
{ {
public AbpTenantManagementDomainMappingProfile() CreateMap<Tenant, TenantConfiguration>()
{ .ForMember(ti => ti.ConnectionStrings, opts =>
CreateMap<Tenant, TenantConfiguration>() {
.ForMember(ti => ti.ConnectionStrings, opts => opts.MapFrom((tenant, ti) =>
{ {
opts.MapFrom((tenant, ti) => var connStrings = new ConnectionStrings();
{
var connStrings = new ConnectionStrings();
foreach (var connectionString in tenant.ConnectionStrings) foreach (var connectionString in tenant.ConnectionStrings)
{ {
connStrings[connectionString.Name] = connectionString.Value; connStrings[connectionString.Name] = connectionString.Value;
} }
return connStrings; return connStrings;
}); });
}) })
.ForMember(x => x.IsActive, x => x.Ignore()); .ForMember(x => x.IsActive, x => x.Ignore());
CreateMap<Tenant, TenantEto>(); CreateMap<Tenant, TenantEto>();
}
} }
} }

61
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/AbpTenantManagementDomainModule.cs

@ -10,43 +10,42 @@ using Volo.Abp.ObjectExtending;
using Volo.Abp.ObjectExtending.Modularity; using Volo.Abp.ObjectExtending.Modularity;
using Volo.Abp.Threading; using Volo.Abp.Threading;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
[DependsOn(typeof(AbpMultiTenancyModule))]
[DependsOn(typeof(AbpTenantManagementDomainSharedModule))]
[DependsOn(typeof(AbpDataModule))]
[DependsOn(typeof(AbpDddDomainModule))]
[DependsOn(typeof(AbpAutoMapperModule))]
[DependsOn(typeof(AbpCachingModule))]
public class AbpTenantManagementDomainModule : AbpModule
{ {
[DependsOn(typeof(AbpMultiTenancyModule))] private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
[DependsOn(typeof(AbpTenantManagementDomainSharedModule))]
[DependsOn(typeof(AbpDataModule))] public override void ConfigureServices(ServiceConfigurationContext context)
[DependsOn(typeof(AbpDddDomainModule))]
[DependsOn(typeof(AbpAutoMapperModule))]
[DependsOn(typeof(AbpCachingModule))]
public class AbpTenantManagementDomainModule : AbpModule
{ {
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); context.Services.AddAutoMapperObjectMapper<AbpTenantManagementDomainModule>();
public override void ConfigureServices(ServiceConfigurationContext context) Configure<AbpAutoMapperOptions>(options =>
{ {
context.Services.AddAutoMapperObjectMapper<AbpTenantManagementDomainModule>(); options.AddProfile<AbpTenantManagementDomainMappingProfile>(validate: true);
});
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<AbpTenantManagementDomainMappingProfile>(validate: true);
});
Configure<AbpDistributedEntityEventOptions>(options => Configure<AbpDistributedEntityEventOptions>(options =>
{ {
options.EtoMappings.Add<Tenant, TenantEto>(); options.EtoMappings.Add<Tenant, TenantEto>();
}); });
} }
public override void PostConfigureServices(ServiceConfigurationContext context) public override void PostConfigureServices(ServiceConfigurationContext context)
{
OneTimeRunner.Run(() =>
{ {
OneTimeRunner.Run(() => ModuleExtensionConfigurationHelper.ApplyEntityConfigurationToEntity(
{ TenantManagementModuleExtensionConsts.ModuleName,
ModuleExtensionConfigurationHelper.ApplyEntityConfigurationToEntity( TenantManagementModuleExtensionConsts.EntityNames.Tenant,
TenantManagementModuleExtensionConsts.ModuleName, typeof(Tenant)
TenantManagementModuleExtensionConsts.EntityNames.Tenant, );
typeof(Tenant) });
);
});
}
} }
} }

13
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantManager.cs

@ -2,13 +2,12 @@
using JetBrains.Annotations; using JetBrains.Annotations;
using Volo.Abp.Domain.Services; using Volo.Abp.Domain.Services;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public interface ITenantManager : IDomainService
{ {
public interface ITenantManager : IDomainService [NotNull]
{ Task<Tenant> CreateAsync([NotNull] string name);
[NotNull]
Task<Tenant> CreateAsync([NotNull] string name);
Task ChangeNameAsync([NotNull] Tenant tenant, [NotNull] string name); Task ChangeNameAsync([NotNull] Tenant tenant, [NotNull] string name);
}
} }

55
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantRepository.cs

@ -4,37 +4,36 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public interface ITenantRepository : IBasicRepository<Tenant, Guid>
{ {
public interface ITenantRepository : IBasicRepository<Tenant, Guid> Task<Tenant> FindByNameAsync(
{ string name,
Task<Tenant> FindByNameAsync( bool includeDetails = true,
string name, CancellationToken cancellationToken = default);
bool includeDetails = true,
CancellationToken cancellationToken = default);
[Obsolete("Use FindByNameAsync method.")] [Obsolete("Use FindByNameAsync method.")]
Tenant FindByName( Tenant FindByName(
string name, string name,
bool includeDetails = true bool includeDetails = true
); );
[Obsolete("Use FindAsync method.")] [Obsolete("Use FindAsync method.")]
Tenant FindById( Tenant FindById(
Guid id, Guid id,
bool includeDetails = true bool includeDetails = true
); );
Task<List<Tenant>> GetListAsync( Task<List<Tenant>> GetListAsync(
string sorting = null, string sorting = null,
int maxResultCount = int.MaxValue, int maxResultCount = int.MaxValue,
int skipCount = 0, int skipCount = 0,
string filter = null, string filter = null,
bool includeDetails = false, bool includeDetails = false,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
Task<long> GetCountAsync( Task<long> GetCountAsync(
string filter = null, string filter = null,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
}
} }

105
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs

@ -4,76 +4,75 @@ using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using Volo.Abp.Domain.Entities.Auditing; using Volo.Abp.Domain.Entities.Auditing;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class Tenant : FullAuditedAggregateRoot<Guid>
{ {
public class Tenant : FullAuditedAggregateRoot<Guid> public virtual string Name { get; protected set; }
{
public virtual string Name { get; protected set; }
public virtual List<TenantConnectionString> ConnectionStrings { get; protected set; } public virtual List<TenantConnectionString> ConnectionStrings { get; protected set; }
protected Tenant() protected Tenant()
{ {
} }
protected internal Tenant(Guid id, [NotNull] string name) protected internal Tenant(Guid id, [NotNull] string name)
: base(id) : base(id)
{ {
SetName(name); SetName(name);
ConnectionStrings = new List<TenantConnectionString>(); ConnectionStrings = new List<TenantConnectionString>();
} }
[CanBeNull] [CanBeNull]
public virtual string FindDefaultConnectionString() public virtual string FindDefaultConnectionString()
{ {
return FindConnectionString(Data.ConnectionStrings.DefaultConnectionStringName); return FindConnectionString(Data.ConnectionStrings.DefaultConnectionStringName);
} }
[CanBeNull] [CanBeNull]
public virtual string FindConnectionString(string name) public virtual string FindConnectionString(string name)
{ {
return ConnectionStrings.FirstOrDefault(c => c.Name == name)?.Value; return ConnectionStrings.FirstOrDefault(c => c.Name == name)?.Value;
} }
public virtual void SetDefaultConnectionString(string connectionString) public virtual void SetDefaultConnectionString(string connectionString)
{ {
SetConnectionString(Data.ConnectionStrings.DefaultConnectionStringName, connectionString); SetConnectionString(Data.ConnectionStrings.DefaultConnectionStringName, connectionString);
} }
public virtual void SetConnectionString(string name, string connectionString) public virtual void SetConnectionString(string name, string connectionString)
{
var tenantConnectionString = ConnectionStrings.FirstOrDefault(x => x.Name == name);
if (tenantConnectionString != null)
{ {
var tenantConnectionString = ConnectionStrings.FirstOrDefault(x => x.Name == name); tenantConnectionString.SetValue(connectionString);
if (tenantConnectionString != null)
{
tenantConnectionString.SetValue(connectionString);
}
else
{
ConnectionStrings.Add(new TenantConnectionString(Id, name, connectionString));
}
} }
else
public virtual void RemoveDefaultConnectionString()
{ {
RemoveConnectionString(Data.ConnectionStrings.DefaultConnectionStringName); ConnectionStrings.Add(new TenantConnectionString(Id, name, connectionString));
} }
}
public virtual void RemoveConnectionString(string name) public virtual void RemoveDefaultConnectionString()
{ {
var tenantConnectionString = ConnectionStrings.FirstOrDefault(x => x.Name == name); RemoveConnectionString(Data.ConnectionStrings.DefaultConnectionStringName);
}
if (tenantConnectionString != null) public virtual void RemoveConnectionString(string name)
{ {
ConnectionStrings.Remove(tenantConnectionString); var tenantConnectionString = ConnectionStrings.FirstOrDefault(x => x.Name == name);
}
}
protected internal virtual void SetName([NotNull] string name) if (tenantConnectionString != null)
{ {
Name = Check.NotNullOrWhiteSpace(name, nameof(name), TenantConsts.MaxNameLength); ConnectionStrings.Remove(tenantConnectionString);
} }
} }
}
protected internal virtual void SetName([NotNull] string name)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name), TenantConsts.MaxNameLength);
}
}

45
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantCacheItem.cs

@ -1,36 +1,35 @@
using System; using System;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
[Serializable]
[IgnoreMultiTenancy]
public class TenantCacheItem
{ {
[Serializable] private const string CacheKeyFormat = "i:{0},n:{1}";
[IgnoreMultiTenancy]
public class TenantCacheItem
{
private const string CacheKeyFormat = "i:{0},n:{1}";
public TenantConfiguration Value { get; set; } public TenantConfiguration Value { get; set; }
public TenantCacheItem() public TenantCacheItem()
{ {
} }
public TenantCacheItem(TenantConfiguration value) public TenantCacheItem(TenantConfiguration value)
{ {
Value = value; Value = value;
} }
public static string CalculateCacheKey(Guid? id, string name) public static string CalculateCacheKey(Guid? id, string name)
{
if (id == null && name.IsNullOrWhiteSpace())
{ {
if (id == null && name.IsNullOrWhiteSpace()) throw new AbpException("Both id and name can't be invalid.");
{
throw new AbpException("Both id and name can't be invalid.");
}
return string.Format(CacheKeyFormat,
id?.ToString() ?? "null",
(name.IsNullOrWhiteSpace() ? "null" : name));
} }
return string.Format(CacheKeyFormat,
id?.ToString() ?? "null",
(name.IsNullOrWhiteSpace() ? "null" : name));
} }
} }

25
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantCacheItemInvalidator.cs

@ -4,21 +4,20 @@ using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events; using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.EventBus; using Volo.Abp.EventBus;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class TenantCacheItemInvalidator : ILocalEventHandler<EntityChangedEventData<Tenant>>, ITransientDependency
{ {
public class TenantCacheItemInvalidator : ILocalEventHandler<EntityChangedEventData<Tenant>>, ITransientDependency protected IDistributedCache<TenantCacheItem> Cache { get; }
{
protected IDistributedCache<TenantCacheItem> Cache { get; }
public TenantCacheItemInvalidator(IDistributedCache<TenantCacheItem> cache) public TenantCacheItemInvalidator(IDistributedCache<TenantCacheItem> cache)
{ {
Cache = cache; Cache = cache;
} }
public virtual async Task HandleEventAsync(EntityChangedEventData<Tenant> eventData) public virtual async Task HandleEventAsync(EntityChangedEventData<Tenant> eventData)
{ {
await Cache.RemoveAsync(TenantCacheItem.CalculateCacheKey(eventData.Entity.Id, null), considerUow: true); await Cache.RemoveAsync(TenantCacheItem.CalculateCacheKey(eventData.Entity.Id, null), considerUow: true);
await Cache.RemoveAsync(TenantCacheItem.CalculateCacheKey(null, eventData.Entity.Name), considerUow: true); await Cache.RemoveAsync(TenantCacheItem.CalculateCacheKey(null, eventData.Entity.Name), considerUow: true);
}
} }
} }

49
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantConnectionString.cs

@ -2,36 +2,35 @@ using System;
using JetBrains.Annotations; using JetBrains.Annotations;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class TenantConnectionString : Entity
{ {
public class TenantConnectionString : Entity public virtual Guid TenantId { get; protected set; }
{
public virtual Guid TenantId { get; protected set; }
public virtual string Name { get; protected set; } public virtual string Name { get; protected set; }
public virtual string Value { get; protected set; } public virtual string Value { get; protected set; }
protected TenantConnectionString() protected TenantConnectionString()
{ {
} }
public TenantConnectionString(Guid tenantId, [NotNull] string name, [NotNull] string value) public TenantConnectionString(Guid tenantId, [NotNull] string name, [NotNull] string value)
{ {
TenantId = tenantId; TenantId = tenantId;
Name = Check.NotNullOrWhiteSpace(name, nameof(name), TenantConnectionStringConsts.MaxNameLength); Name = Check.NotNullOrWhiteSpace(name, nameof(name), TenantConnectionStringConsts.MaxNameLength);
SetValue(value); SetValue(value);
} }
public virtual void SetValue([NotNull] string value) public virtual void SetValue([NotNull] string value)
{ {
Value = Check.NotNullOrWhiteSpace(value, nameof(value), TenantConnectionStringConsts.MaxValueLength); Value = Check.NotNullOrWhiteSpace(value, nameof(value), TenantConnectionStringConsts.MaxValueLength);
} }
public override object[] GetKeys() public override object[] GetKeys()
{ {
return new object[] { TenantId, Name }; return new object[] { TenantId, Name };
}
} }
} }

55
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs

@ -2,42 +2,41 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Domain.Services; using Volo.Abp.Domain.Services;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class TenantManager : DomainService, ITenantManager
{ {
public class TenantManager : DomainService, ITenantManager protected ITenantRepository TenantRepository { get; }
{
protected ITenantRepository TenantRepository { get; }
public TenantManager(ITenantRepository tenantRepository) public TenantManager(ITenantRepository tenantRepository)
{ {
TenantRepository = tenantRepository; TenantRepository = tenantRepository;
} }
public virtual async Task<Tenant> CreateAsync(string name) public virtual async Task<Tenant> CreateAsync(string name)
{ {
Check.NotNull(name, nameof(name)); Check.NotNull(name, nameof(name));
await ValidateNameAsync(name); await ValidateNameAsync(name);
return new Tenant(GuidGenerator.Create(), name); return new Tenant(GuidGenerator.Create(), name);
} }
public virtual async Task ChangeNameAsync(Tenant tenant, string name) public virtual async Task ChangeNameAsync(Tenant tenant, string name)
{ {
Check.NotNull(tenant, nameof(tenant)); Check.NotNull(tenant, nameof(tenant));
Check.NotNull(name, nameof(name)); Check.NotNull(name, nameof(name));
await ValidateNameAsync(name, tenant.Id); await ValidateNameAsync(name, tenant.Id);
tenant.SetName(name); tenant.SetName(name);
} }
protected virtual async Task ValidateNameAsync(string name, Guid? expectedId = null) protected virtual async Task ValidateNameAsync(string name, Guid? expectedId = null)
{
var tenant = await TenantRepository.FindByNameAsync(name);
if (tenant != null && tenant.Id != expectedId)
{ {
var tenant = await TenantRepository.FindByNameAsync(name); throw new UserFriendlyException("Duplicate tenancy name: " + name); //TODO: A domain exception would be better..?
if (tenant != null && tenant.Id != expectedId)
{
throw new UserFriendlyException("Duplicate tenancy name: " + name); //TODO: A domain exception would be better..?
}
} }
} }
} }

191
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs

@ -6,132 +6,131 @@ using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.ObjectMapping; using Volo.Abp.ObjectMapping;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class TenantStore : ITenantStore, ITransientDependency
{ {
public class TenantStore : ITenantStore, ITransientDependency protected ITenantRepository TenantRepository { get; }
protected IObjectMapper<AbpTenantManagementDomainModule> ObjectMapper { get; }
protected ICurrentTenant CurrentTenant { get; }
protected IDistributedCache<TenantCacheItem> Cache { get; }
public TenantStore(
ITenantRepository tenantRepository,
IObjectMapper<AbpTenantManagementDomainModule> objectMapper,
ICurrentTenant currentTenant,
IDistributedCache<TenantCacheItem> cache)
{ {
protected ITenantRepository TenantRepository { get; } TenantRepository = tenantRepository;
protected IObjectMapper<AbpTenantManagementDomainModule> ObjectMapper { get; } ObjectMapper = objectMapper;
protected ICurrentTenant CurrentTenant { get; } CurrentTenant = currentTenant;
protected IDistributedCache<TenantCacheItem> Cache { get; } Cache = cache;
}
public TenantStore(
ITenantRepository tenantRepository,
IObjectMapper<AbpTenantManagementDomainModule> objectMapper,
ICurrentTenant currentTenant,
IDistributedCache<TenantCacheItem> cache)
{
TenantRepository = tenantRepository;
ObjectMapper = objectMapper;
CurrentTenant = currentTenant;
Cache = cache;
}
public virtual async Task<TenantConfiguration> FindAsync(string name) public virtual async Task<TenantConfiguration> FindAsync(string name)
{ {
return (await GetCacheItemAsync(null, name)).Value; return (await GetCacheItemAsync(null, name)).Value;
} }
public virtual async Task<TenantConfiguration> FindAsync(Guid id) public virtual async Task<TenantConfiguration> FindAsync(Guid id)
{ {
return (await GetCacheItemAsync(id, null)).Value; return (await GetCacheItemAsync(id, null)).Value;
} }
[Obsolete("Use FindAsync method.")] [Obsolete("Use FindAsync method.")]
public virtual TenantConfiguration Find(string name) public virtual TenantConfiguration Find(string name)
{ {
return (GetCacheItem(null, name)).Value; return (GetCacheItem(null, name)).Value;
} }
[Obsolete("Use FindAsync method.")] [Obsolete("Use FindAsync method.")]
public virtual TenantConfiguration Find(Guid id) public virtual TenantConfiguration Find(Guid id)
{
return (GetCacheItem(id, null)).Value;
}
protected virtual async Task<TenantCacheItem> GetCacheItemAsync(Guid? id, string name)
{
var cacheKey = CalculateCacheKey(id, name);
var cacheItem = await Cache.GetAsync(cacheKey, considerUow: true);
if (cacheItem != null)
{ {
return (GetCacheItem(id, null)).Value; return cacheItem;
} }
protected virtual async Task<TenantCacheItem> GetCacheItemAsync(Guid? id, string name) if (id.HasValue)
{ {
var cacheKey = CalculateCacheKey(id, name); using (CurrentTenant.Change(null)) //TODO: No need this if we can implement to define host side (or tenant-independent) entities!
var cacheItem = await Cache.GetAsync(cacheKey, considerUow: true);
if (cacheItem != null)
{ {
return cacheItem; var tenant = await TenantRepository.FindAsync(id.Value);
return await SetCacheAsync(cacheKey, tenant);
} }
}
if (id.HasValue) if (!name.IsNullOrWhiteSpace())
{
using (CurrentTenant.Change(null)) //TODO: No need this if we can implement to define host side (or tenant-independent) entities!
{ {
using (CurrentTenant.Change(null)) //TODO: No need this if we can implement to define host side (or tenant-independent) entities! var tenant = await TenantRepository.FindByNameAsync(name);
{ return await SetCacheAsync(cacheKey, tenant);
var tenant = await TenantRepository.FindAsync(id.Value);
return await SetCacheAsync(cacheKey, tenant);
}
} }
}
if (!name.IsNullOrWhiteSpace()) throw new AbpException("Both id and name can't be invalid.");
{ }
using (CurrentTenant.Change(null)) //TODO: No need this if we can implement to define host side (or tenant-independent) entities!
{
var tenant = await TenantRepository.FindByNameAsync(name);
return await SetCacheAsync(cacheKey, tenant);
}
}
throw new AbpException("Both id and name can't be invalid."); protected virtual async Task<TenantCacheItem> SetCacheAsync(string cacheKey, [CanBeNull] Tenant tenant)
} {
var tenantConfiguration = tenant != null ? ObjectMapper.Map<Tenant, TenantConfiguration>(tenant) : null;
var cacheItem = new TenantCacheItem(tenantConfiguration);
await Cache.SetAsync(cacheKey, cacheItem, considerUow: true);
return cacheItem;
}
protected virtual async Task<TenantCacheItem> SetCacheAsync(string cacheKey, [CanBeNull]Tenant tenant) [Obsolete("Use GetCacheItemAsync method.")]
protected virtual TenantCacheItem GetCacheItem(Guid? id, string name)
{
var cacheKey = CalculateCacheKey(id, name);
var cacheItem = Cache.Get(cacheKey, considerUow: true);
if (cacheItem != null)
{ {
var tenantConfiguration = tenant != null ? ObjectMapper.Map<Tenant, TenantConfiguration>(tenant) : null;
var cacheItem = new TenantCacheItem(tenantConfiguration);
await Cache.SetAsync(cacheKey, cacheItem, considerUow: true);
return cacheItem; return cacheItem;
} }
[Obsolete("Use GetCacheItemAsync method.")] if (id.HasValue)
protected virtual TenantCacheItem GetCacheItem(Guid? id, string name)
{ {
var cacheKey = CalculateCacheKey(id, name); using (CurrentTenant.Change(null)) //TODO: No need this if we can implement to define host side (or tenant-independent) entities!
var cacheItem = Cache.Get(cacheKey, considerUow: true);
if (cacheItem != null)
{
return cacheItem;
}
if (id.HasValue)
{ {
using (CurrentTenant.Change(null)) //TODO: No need this if we can implement to define host side (or tenant-independent) entities! var tenant = TenantRepository.FindById(id.Value);
{ return SetCache(cacheKey, tenant);
var tenant = TenantRepository.FindById(id.Value);
return SetCache(cacheKey, tenant);
}
} }
}
if (!name.IsNullOrWhiteSpace()) if (!name.IsNullOrWhiteSpace())
{
using (CurrentTenant.Change(null)) //TODO: No need this if we can implement to define host side (or tenant-independent) entities!
{ {
using (CurrentTenant.Change(null)) //TODO: No need this if we can implement to define host side (or tenant-independent) entities! var tenant = TenantRepository.FindByName(name);
{ return SetCache(cacheKey, tenant);
var tenant = TenantRepository.FindByName(name);
return SetCache(cacheKey, tenant);
}
} }
throw new AbpException("Both id and name can't be invalid.");
} }
[Obsolete("Use SetCacheAsync method.")] throw new AbpException("Both id and name can't be invalid.");
protected virtual TenantCacheItem SetCache(string cacheKey, [CanBeNull]Tenant tenant) }
{
var tenantConfiguration = tenant != null ? ObjectMapper.Map<Tenant, TenantConfiguration>(tenant) : null;
var cacheItem = new TenantCacheItem(tenantConfiguration);
Cache.Set(cacheKey, cacheItem, considerUow: true);
return cacheItem;
}
protected virtual string CalculateCacheKey(Guid? id, string name) [Obsolete("Use SetCacheAsync method.")]
{ protected virtual TenantCacheItem SetCache(string cacheKey, [CanBeNull] Tenant tenant)
return TenantCacheItem.CalculateCacheKey(id, name); {
} var tenantConfiguration = tenant != null ? ObjectMapper.Map<Tenant, TenantConfiguration>(tenant) : null;
var cacheItem = new TenantCacheItem(tenantConfiguration);
Cache.Set(cacheKey, cacheItem, considerUow: true);
return cacheItem;
}
protected virtual string CalculateCacheKey(Guid? id, string name)
{
return TenantCacheItem.CalculateCacheKey(id, name);
} }
} }

59
modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs

@ -2,50 +2,49 @@ using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.Modeling; using Volo.Abp.EntityFrameworkCore.Modeling;
namespace Volo.Abp.TenantManagement.EntityFrameworkCore namespace Volo.Abp.TenantManagement.EntityFrameworkCore;
public static class AbpTenantManagementDbContextModelCreatingExtensions
{ {
public static class AbpTenantManagementDbContextModelCreatingExtensions public static void ConfigureTenantManagement(
this ModelBuilder builder)
{ {
public static void ConfigureTenantManagement( Check.NotNull(builder, nameof(builder));
this ModelBuilder builder)
{
Check.NotNull(builder, nameof(builder));
if (builder.IsTenantOnlyDatabase()) if (builder.IsTenantOnlyDatabase())
{ {
return; return;
} }
builder.Entity<Tenant>(b => builder.Entity<Tenant>(b =>
{ {
b.ToTable(AbpTenantManagementDbProperties.DbTablePrefix + "Tenants", AbpTenantManagementDbProperties.DbSchema); b.ToTable(AbpTenantManagementDbProperties.DbTablePrefix + "Tenants", AbpTenantManagementDbProperties.DbSchema);
b.ConfigureByConvention(); b.ConfigureByConvention();
b.Property(t => t.Name).IsRequired().HasMaxLength(TenantConsts.MaxNameLength); b.Property(t => t.Name).IsRequired().HasMaxLength(TenantConsts.MaxNameLength);
b.HasMany(u => u.ConnectionStrings).WithOne().HasForeignKey(uc => uc.TenantId).IsRequired(); b.HasMany(u => u.ConnectionStrings).WithOne().HasForeignKey(uc => uc.TenantId).IsRequired();
b.HasIndex(u => u.Name); b.HasIndex(u => u.Name);
b.ApplyObjectExtensionMappings(); b.ApplyObjectExtensionMappings();
}); });
builder.Entity<TenantConnectionString>(b => builder.Entity<TenantConnectionString>(b =>
{ {
b.ToTable(AbpTenantManagementDbProperties.DbTablePrefix + "TenantConnectionStrings", AbpTenantManagementDbProperties.DbSchema); b.ToTable(AbpTenantManagementDbProperties.DbTablePrefix + "TenantConnectionStrings", AbpTenantManagementDbProperties.DbSchema);
b.ConfigureByConvention(); b.ConfigureByConvention();
b.HasKey(x => new { x.TenantId, x.Name }); b.HasKey(x => new { x.TenantId, x.Name });
b.Property(cs => cs.Name).IsRequired().HasMaxLength(TenantConnectionStringConsts.MaxNameLength); b.Property(cs => cs.Name).IsRequired().HasMaxLength(TenantConnectionStringConsts.MaxNameLength);
b.Property(cs => cs.Value).IsRequired().HasMaxLength(TenantConnectionStringConsts.MaxValueLength); b.Property(cs => cs.Value).IsRequired().HasMaxLength(TenantConnectionStringConsts.MaxValueLength);
b.ApplyObjectExtensionMappings(); b.ApplyObjectExtensionMappings();
}); });
builder.TryConfigureObjectExtensions<TenantManagementDbContext>(); builder.TryConfigureObjectExtensions<TenantManagementDbContext>();
}
} }
} }

19
modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementEntityFrameworkCoreModule.cs

@ -2,18 +2,17 @@
using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace Volo.Abp.TenantManagement.EntityFrameworkCore namespace Volo.Abp.TenantManagement.EntityFrameworkCore;
[DependsOn(typeof(AbpTenantManagementDomainModule))]
[DependsOn(typeof(AbpEntityFrameworkCoreModule))]
public class AbpTenantManagementEntityFrameworkCoreModule : AbpModule
{ {
[DependsOn(typeof(AbpTenantManagementDomainModule))] public override void ConfigureServices(ServiceConfigurationContext context)
[DependsOn(typeof(AbpEntityFrameworkCoreModule))]
public class AbpTenantManagementEntityFrameworkCoreModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) context.Services.AddAbpDbContext<TenantManagementDbContext>(options =>
{ {
context.Services.AddAbpDbContext<TenantManagementDbContext>(options => options.AddDefaultRepositories<ITenantManagementDbContext>();
{ });
options.AddDefaultRepositories<ITenantManagementDbContext>();
});
}
} }
} }

137
modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs

@ -8,84 +8,83 @@ using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.TenantManagement.EntityFrameworkCore namespace Volo.Abp.TenantManagement.EntityFrameworkCore;
public class EfCoreTenantRepository : EfCoreRepository<ITenantManagementDbContext, Tenant, Guid>, ITenantRepository
{ {
public class EfCoreTenantRepository : EfCoreRepository<ITenantManagementDbContext, Tenant, Guid>, ITenantRepository public EfCoreTenantRepository(IDbContextProvider<ITenantManagementDbContext> dbContextProvider)
: base(dbContextProvider)
{ {
public EfCoreTenantRepository(IDbContextProvider<ITenantManagementDbContext> dbContextProvider)
: base(dbContextProvider)
{
} }
public virtual async Task<Tenant> FindByNameAsync( public virtual async Task<Tenant> FindByNameAsync(
string name, string name,
bool includeDetails = true, bool includeDetails = true,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
return await (await GetDbSetAsync()) return await (await GetDbSetAsync())
.IncludeDetails(includeDetails) .IncludeDetails(includeDetails)
.OrderBy(t => t.Id) .OrderBy(t => t.Id)
.FirstOrDefaultAsync(t => t.Name == name, GetCancellationToken(cancellationToken)); .FirstOrDefaultAsync(t => t.Name == name, GetCancellationToken(cancellationToken));
} }
[Obsolete("Use FindByNameAsync method.")] [Obsolete("Use FindByNameAsync method.")]
public virtual Tenant FindByName(string name, bool includeDetails = true) public virtual Tenant FindByName(string name, bool includeDetails = true)
{ {
return DbSet return DbSet
.IncludeDetails(includeDetails) .IncludeDetails(includeDetails)
.OrderBy(t => t.Id) .OrderBy(t => t.Id)
.FirstOrDefault(t => t.Name == name); .FirstOrDefault(t => t.Name == name);
} }
[Obsolete("Use FindAsync method.")] [Obsolete("Use FindAsync method.")]
public virtual Tenant FindById(Guid id, bool includeDetails = true) public virtual Tenant FindById(Guid id, bool includeDetails = true)
{ {
return DbSet return DbSet
.IncludeDetails(includeDetails) .IncludeDetails(includeDetails)
.OrderBy(t => t.Id) .OrderBy(t => t.Id)
.FirstOrDefault(t => t.Id == id); .FirstOrDefault(t => t.Id == id);
} }
public virtual async Task<List<Tenant>> GetListAsync( public virtual async Task<List<Tenant>> GetListAsync(
string sorting = null, string sorting = null,
int maxResultCount = int.MaxValue, int maxResultCount = int.MaxValue,
int skipCount = 0, int skipCount = 0,
string filter = null, string filter = null,
bool includeDetails = false, bool includeDetails = false,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
return await (await GetDbSetAsync()) return await (await GetDbSetAsync())
.IncludeDetails(includeDetails) .IncludeDetails(includeDetails)
.WhereIf( .WhereIf(
!filter.IsNullOrWhiteSpace(), !filter.IsNullOrWhiteSpace(),
u => u =>
u.Name.Contains(filter) u.Name.Contains(filter)
) )
.OrderBy(sorting.IsNullOrEmpty() ? nameof(Tenant.Name) : sorting) .OrderBy(sorting.IsNullOrEmpty() ? nameof(Tenant.Name) : sorting)
.PageBy(skipCount, maxResultCount) .PageBy(skipCount, maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken)); .ToListAsync(GetCancellationToken(cancellationToken));
} }
public virtual async Task<long> GetCountAsync(string filter = null, CancellationToken cancellationToken = default) public virtual async Task<long> GetCountAsync(string filter = null, CancellationToken cancellationToken = default)
{ {
return await (await GetQueryableAsync()) return await (await GetQueryableAsync())
.WhereIf( .WhereIf(
!filter.IsNullOrWhiteSpace(), !filter.IsNullOrWhiteSpace(),
u => u =>
u.Name.Contains(filter) u.Name.Contains(filter)
).CountAsync(cancellationToken: cancellationToken); ).CountAsync(cancellationToken: cancellationToken);
} }
[Obsolete("Use WithDetailsAsync method.")] [Obsolete("Use WithDetailsAsync method.")]
public override IQueryable<Tenant> WithDetails() public override IQueryable<Tenant> WithDetails()
{ {
return GetQueryable().IncludeDetails(); return GetQueryable().IncludeDetails();
} }
public override async Task<IQueryable<Tenant>> WithDetailsAsync() public override async Task<IQueryable<Tenant>> WithDetailsAsync()
{ {
return (await GetQueryableAsync()).IncludeDetails(); return (await GetQueryableAsync()).IncludeDetails();
}
} }
} }

15
modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/ITenantManagementDbContext.cs

@ -3,14 +3,13 @@ using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
namespace Volo.Abp.TenantManagement.EntityFrameworkCore namespace Volo.Abp.TenantManagement.EntityFrameworkCore;
[IgnoreMultiTenancy]
[ConnectionStringName(AbpTenantManagementDbProperties.ConnectionStringName)]
public interface ITenantManagementDbContext : IEfCoreDbContext
{ {
[IgnoreMultiTenancy] DbSet<Tenant> Tenants { get; }
[ConnectionStringName(AbpTenantManagementDbProperties.ConnectionStringName)]
public interface ITenantManagementDbContext : IEfCoreDbContext
{
DbSet<Tenant> Tenants { get; }
DbSet<TenantConnectionString> TenantConnectionStrings { get; } DbSet<TenantConnectionString> TenantConnectionStrings { get; }
}
} }

31
modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/TenantManagementDbContext.cs

@ -3,26 +3,25 @@ using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
namespace Volo.Abp.TenantManagement.EntityFrameworkCore namespace Volo.Abp.TenantManagement.EntityFrameworkCore;
[IgnoreMultiTenancy]
[ConnectionStringName(AbpTenantManagementDbProperties.ConnectionStringName)]
public class TenantManagementDbContext : AbpDbContext<TenantManagementDbContext>, ITenantManagementDbContext
{ {
[IgnoreMultiTenancy] public DbSet<Tenant> Tenants { get; set; }
[ConnectionStringName(AbpTenantManagementDbProperties.ConnectionStringName)]
public class TenantManagementDbContext : AbpDbContext<TenantManagementDbContext>, ITenantManagementDbContext
{
public DbSet<Tenant> Tenants { get; set; }
public DbSet<TenantConnectionString> TenantConnectionStrings { get; set; } public DbSet<TenantConnectionString> TenantConnectionStrings { get; set; }
public TenantManagementDbContext(DbContextOptions<TenantManagementDbContext> options) public TenantManagementDbContext(DbContextOptions<TenantManagementDbContext> options)
: base(options) : base(options)
{ {
} }
protected override void OnModelCreating(ModelBuilder builder) protected override void OnModelCreating(ModelBuilder builder)
{ {
base.OnModelCreating(builder); base.OnModelCreating(builder);
builder.ConfigureTenantManagement(); builder.ConfigureTenantManagement();
}
} }
} }

21
modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/TenantManagementEfCoreQueryableExtensions.cs

@ -1,19 +1,18 @@
using System.Linq; using System.Linq;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Volo.Abp.TenantManagement.EntityFrameworkCore namespace Volo.Abp.TenantManagement.EntityFrameworkCore;
public static class TenantManagementEfCoreQueryableExtensions
{ {
public static class TenantManagementEfCoreQueryableExtensions public static IQueryable<Tenant> IncludeDetails(this IQueryable<Tenant> queryable, bool include = true)
{ {
public static IQueryable<Tenant> IncludeDetails(this IQueryable<Tenant> queryable, bool include = true) if (!include)
{ {
if (!include) return queryable;
{
return queryable;
}
return queryable
.Include(x => x.ConnectionStrings);
} }
return queryable
.Include(x => x.ConnectionStrings);
} }
} }

7
modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi.Client/ClientProxies/TenantClientProxy.cs

@ -1,8 +1,7 @@
// This file is part of TenantClientProxy, you can customize it here // This file is part of TenantClientProxy, you can customize it here
// ReSharper disable once CheckNamespace // ReSharper disable once CheckNamespace
namespace Volo.Abp.TenantManagement.ClientProxies namespace Volo.Abp.TenantManagement.ClientProxies;
public partial class TenantClientProxy
{ {
public partial class TenantClientProxy
{
}
} }

31
modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi.Client/Volo/Abp/TenantManagement/AbpTenantManagementHttpApiClientModule.cs

@ -3,24 +3,23 @@ using Volo.Abp.Http.Client;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
[DependsOn(
typeof(AbpTenantManagementApplicationContractsModule),
typeof(AbpHttpClientModule))]
public class AbpTenantManagementHttpApiClientModule : AbpModule
{ {
[DependsOn( public override void ConfigureServices(ServiceConfigurationContext context)
typeof(AbpTenantManagementApplicationContractsModule),
typeof(AbpHttpClientModule))]
public class AbpTenantManagementHttpApiClientModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) context.Services.AddStaticHttpClientProxies(
{ typeof(AbpTenantManagementApplicationContractsModule).Assembly,
context.Services.AddStaticHttpClientProxies( TenantManagementRemoteServiceConsts.RemoteServiceName
typeof(AbpTenantManagementApplicationContractsModule).Assembly, );
TenantManagementRemoteServiceConsts.RemoteServiceName
);
Configure<AbpVirtualFileSystemOptions>(options => Configure<AbpVirtualFileSystemOptions>(options =>
{ {
options.FileSets.AddEmbedded<AbpTenantManagementHttpApiClientModule>(); options.FileSets.AddEmbedded<AbpTenantManagementHttpApiClientModule>();
}); });
}
} }
} }

47
modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi/Volo/Abp/TenantManagement/AbpTenantManagementHttpApiModule.cs

@ -7,33 +7,32 @@ using Volo.Abp.Modularity;
using Volo.Abp.TenantManagement.Localization; using Volo.Abp.TenantManagement.Localization;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
[DependsOn(
typeof(AbpTenantManagementApplicationContractsModule),
typeof(AbpFeatureManagementHttpApiModule),
typeof(AbpAspNetCoreMvcModule)
)]
public class AbpTenantManagementHttpApiModule : AbpModule
{ {
[DependsOn( public override void PreConfigureServices(ServiceConfigurationContext context)
typeof(AbpTenantManagementApplicationContractsModule),
typeof(AbpFeatureManagementHttpApiModule),
typeof(AbpAspNetCoreMvcModule)
)]
public class AbpTenantManagementHttpApiModule : AbpModule
{ {
public override void PreConfigureServices(ServiceConfigurationContext context) PreConfigure<IMvcBuilder>(mvcBuilder =>
{ {
PreConfigure<IMvcBuilder>(mvcBuilder => mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpTenantManagementHttpApiModule).Assembly);
{ });
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpTenantManagementHttpApiModule).Assembly); }
});
}
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpLocalizationOptions>(options =>
{ {
Configure<AbpLocalizationOptions>(options => options.Resources
{ .Get<AbpTenantManagementResource>()
options.Resources .AddBaseTypes(
.Get<AbpTenantManagementResource>() typeof(AbpFeatureManagementResource),
.AddBaseTypes( typeof(AbpUiResource));
typeof(AbpFeatureManagementResource), });
typeof(AbpUiResource));
});
}
} }
} }

117
modules/tenant-management/src/Volo.Abp.TenantManagement.HttpApi/Volo/Abp/TenantManagement/TenantController.cs

@ -4,74 +4,73 @@ using Microsoft.AspNetCore.Mvc;
using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Dtos;
using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
[Controller]
[RemoteService(Name = TenantManagementRemoteServiceConsts.RemoteServiceName)]
[Area(TenantManagementRemoteServiceConsts.ModuleName)]
[Route("api/multi-tenancy/tenants")]
public class TenantController : AbpControllerBase, ITenantAppService //TODO: Throws exception on validation if we inherit from Controller
{ {
[Controller] protected ITenantAppService TenantAppService { get; }
[RemoteService(Name = TenantManagementRemoteServiceConsts.RemoteServiceName)]
[Area(TenantManagementRemoteServiceConsts.ModuleName)]
[Route("api/multi-tenancy/tenants")]
public class TenantController : AbpControllerBase, ITenantAppService //TODO: Throws exception on validation if we inherit from Controller
{
protected ITenantAppService TenantAppService { get; }
public TenantController(ITenantAppService tenantAppService) public TenantController(ITenantAppService tenantAppService)
{ {
TenantAppService = tenantAppService; TenantAppService = tenantAppService;
} }
[HttpGet] [HttpGet]
[Route("{id}")] [Route("{id}")]
public virtual Task<TenantDto> GetAsync(Guid id) public virtual Task<TenantDto> GetAsync(Guid id)
{ {
return TenantAppService.GetAsync(id); return TenantAppService.GetAsync(id);
} }
[HttpGet] [HttpGet]
public virtual Task<PagedResultDto<TenantDto>> GetListAsync(GetTenantsInput input) public virtual Task<PagedResultDto<TenantDto>> GetListAsync(GetTenantsInput input)
{ {
return TenantAppService.GetListAsync(input); return TenantAppService.GetListAsync(input);
} }
[HttpPost] [HttpPost]
public virtual Task<TenantDto> CreateAsync(TenantCreateDto input) public virtual Task<TenantDto> CreateAsync(TenantCreateDto input)
{ {
ValidateModel(); ValidateModel();
return TenantAppService.CreateAsync(input); return TenantAppService.CreateAsync(input);
} }
[HttpPut] [HttpPut]
[Route("{id}")] [Route("{id}")]
public virtual Task<TenantDto> UpdateAsync(Guid id, TenantUpdateDto input) public virtual Task<TenantDto> UpdateAsync(Guid id, TenantUpdateDto input)
{ {
return TenantAppService.UpdateAsync(id, input); return TenantAppService.UpdateAsync(id, input);
} }
[HttpDelete] [HttpDelete]
[Route("{id}")] [Route("{id}")]
public virtual Task DeleteAsync(Guid id) public virtual Task DeleteAsync(Guid id)
{ {
return TenantAppService.DeleteAsync(id); return TenantAppService.DeleteAsync(id);
} }
[HttpGet] [HttpGet]
[Route("{id}/default-connection-string")] [Route("{id}/default-connection-string")]
public virtual Task<string> GetDefaultConnectionStringAsync(Guid id) public virtual Task<string> GetDefaultConnectionStringAsync(Guid id)
{ {
return TenantAppService.GetDefaultConnectionStringAsync(id); return TenantAppService.GetDefaultConnectionStringAsync(id);
} }
[HttpPut] [HttpPut]
[Route("{id}/default-connection-string")] [Route("{id}/default-connection-string")]
public virtual Task UpdateDefaultConnectionStringAsync(Guid id, string defaultConnectionString) public virtual Task UpdateDefaultConnectionStringAsync(Guid id, string defaultConnectionString)
{ {
return TenantAppService.UpdateDefaultConnectionStringAsync(id, defaultConnectionString); return TenantAppService.UpdateDefaultConnectionStringAsync(id, defaultConnectionString);
} }
[HttpDelete] [HttpDelete]
[Route("{id}/default-connection-string")] [Route("{id}/default-connection-string")]
public virtual Task DeleteDefaultConnectionStringAsync(Guid id) public virtual Task DeleteDefaultConnectionStringAsync(Guid id)
{ {
return TenantAppService.DeleteDefaultConnectionStringAsync(id); return TenantAppService.DeleteDefaultConnectionStringAsync(id);
}
} }
} }

23
modules/tenant-management/src/Volo.Abp.TenantManagement.Installer/Volo/Abp/TenantManagement/AbpTenantManagementInstallerModule.cs

@ -2,20 +2,19 @@
using Volo.Abp.Studio; using Volo.Abp.Studio;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
[DependsOn(
typeof(AbpStudioModuleInstallerModule),
typeof(AbpVirtualFileSystemModule)
)]
public class AbpTenantManagementInstallerModule : AbpModule
{ {
[DependsOn( public override void ConfigureServices(ServiceConfigurationContext context)
typeof(AbpStudioModuleInstallerModule),
typeof(AbpVirtualFileSystemModule)
)]
public class AbpTenantManagementInstallerModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) Configure<AbpVirtualFileSystemOptions>(options =>
{ {
Configure<AbpVirtualFileSystemOptions>(options => options.FileSets.AddEmbedded<AbpTenantManagementInstallerModule>();
{ });
options.FileSets.AddEmbedded<AbpTenantManagementInstallerModule>();
});
}
} }
} }

29
modules/tenant-management/src/Volo.Abp.TenantManagement.Installer/Volo/Abp/TenantManagement/TenantManagementInstallerPipelineBuilder.cs

@ -3,22 +3,21 @@ using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Studio.ModuleInstalling; using Volo.Abp.Studio.ModuleInstalling;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
[Dependency(ServiceLifetime.Transient, ReplaceServices = true)]
[ExposeServices(typeof(IModuleInstallingPipelineBuilder))]
public class AuditLoggingInstallerPipelineBuilder : ModuleInstallingPipelineBuilderBase, IModuleInstallingPipelineBuilder, ITransientDependency
{ {
[Dependency(ServiceLifetime.Transient, ReplaceServices = true)] public async Task<ModuleInstallingPipeline> BuildAsync(ModuleInstallingContext context)
[ExposeServices(typeof(IModuleInstallingPipelineBuilder))]
public class AuditLoggingInstallerPipelineBuilder : ModuleInstallingPipelineBuilderBase, IModuleInstallingPipelineBuilder, ITransientDependency
{ {
public async Task<ModuleInstallingPipeline> BuildAsync(ModuleInstallingContext context) context.AddEfCoreConfigurationMethodDeclaration(
{ new EfCoreConfigurationMethodDeclaration(
context.AddEfCoreConfigurationMethodDeclaration( "Volo.Abp.TenantManagement.EntityFrameworkCore",
new EfCoreConfigurationMethodDeclaration( "ConfigureTenantManagement"
"Volo.Abp.TenantManagement.EntityFrameworkCore", )
"ConfigureTenantManagement" );
)
); return GetBasePipeline(context);
return GetBasePipeline(context);
}
} }
} }

23
modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/AbpTenantManagementMongoDbContextExtensions.cs

@ -1,18 +1,17 @@
using Volo.Abp.MongoDB; using Volo.Abp.MongoDB;
namespace Volo.Abp.TenantManagement.MongoDB namespace Volo.Abp.TenantManagement.MongoDB;
public static class AbpTenantManagementMongoDbContextExtensions
{ {
public static class AbpTenantManagementMongoDbContextExtensions public static void ConfigureTenantManagement(
this IMongoModelBuilder builder)
{ {
public static void ConfigureTenantManagement( Check.NotNull(builder, nameof(builder));
this IMongoModelBuilder builder)
{
Check.NotNull(builder, nameof(builder));
builder.Entity<Tenant>(b => builder.Entity<Tenant>(b =>
{ {
b.CollectionName = AbpTenantManagementDbProperties.DbTablePrefix + "Tenants"; b.CollectionName = AbpTenantManagementDbProperties.DbTablePrefix + "Tenants";
}); });
}
} }
} }

25
modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/AbpTenantManagementMongoDbModule.cs

@ -2,22 +2,21 @@
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.MongoDB; using Volo.Abp.MongoDB;
namespace Volo.Abp.TenantManagement.MongoDB namespace Volo.Abp.TenantManagement.MongoDB;
[DependsOn(
typeof(AbpTenantManagementDomainModule),
typeof(AbpMongoDbModule)
)]
public class AbpTenantManagementMongoDbModule : AbpModule
{ {
[DependsOn( public override void ConfigureServices(ServiceConfigurationContext context)
typeof(AbpTenantManagementDomainModule),
typeof(AbpMongoDbModule)
)]
public class AbpTenantManagementMongoDbModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) context.Services.AddMongoDbContext<TenantManagementMongoDbContext>(options =>
{ {
context.Services.AddMongoDbContext<TenantManagementMongoDbContext>(options => options.AddDefaultRepositories<ITenantManagementMongoDbContext>();
{
options.AddDefaultRepositories<ITenantManagementMongoDbContext>();
options.AddRepository<Tenant, MongoTenantRepository>(); options.AddRepository<Tenant, MongoTenantRepository>();
}); });
}
} }
} }

13
modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/ITenantManagementMongoDbContext.cs

@ -3,12 +3,11 @@ using Volo.Abp.Data;
using Volo.Abp.MongoDB; using Volo.Abp.MongoDB;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
namespace Volo.Abp.TenantManagement.MongoDB namespace Volo.Abp.TenantManagement.MongoDB;
[IgnoreMultiTenancy]
[ConnectionStringName(AbpTenantManagementDbProperties.ConnectionStringName)]
public interface ITenantManagementMongoDbContext : IAbpMongoDbContext
{ {
[IgnoreMultiTenancy] IMongoCollection<Tenant> Tenants { get; }
[ConnectionStringName(AbpTenantManagementDbProperties.ConnectionStringName)]
public interface ITenantManagementMongoDbContext : IAbpMongoDbContext
{
IMongoCollection<Tenant> Tenants { get; }
}
} }

107
modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs

@ -9,67 +9,66 @@ using MongoDB.Driver;
using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.MongoDB; using Volo.Abp.MongoDB;
namespace Volo.Abp.TenantManagement.MongoDB namespace Volo.Abp.TenantManagement.MongoDB;
public class MongoTenantRepository : MongoDbRepository<ITenantManagementMongoDbContext, Tenant, Guid>, ITenantRepository
{ {
public class MongoTenantRepository : MongoDbRepository<ITenantManagementMongoDbContext, Tenant, Guid>, ITenantRepository public MongoTenantRepository(IMongoDbContextProvider<ITenantManagementMongoDbContext> dbContextProvider)
: base(dbContextProvider)
{ {
public MongoTenantRepository(IMongoDbContextProvider<ITenantManagementMongoDbContext> dbContextProvider)
: base(dbContextProvider)
{
} }
public virtual async Task<Tenant> FindByNameAsync( public virtual async Task<Tenant> FindByNameAsync(
string name, string name,
bool includeDetails = true, bool includeDetails = true,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
return await (await GetMongoQueryableAsync(cancellationToken)) return await (await GetMongoQueryableAsync(cancellationToken))
.FirstOrDefaultAsync(t => t.Name == name, GetCancellationToken(cancellationToken)); .FirstOrDefaultAsync(t => t.Name == name, GetCancellationToken(cancellationToken));
} }
[Obsolete("Use FindByNameAsync method.")] [Obsolete("Use FindByNameAsync method.")]
public virtual Tenant FindByName(string name, bool includeDetails = true) public virtual Tenant FindByName(string name, bool includeDetails = true)
{ {
return GetMongoQueryable() return GetMongoQueryable()
.FirstOrDefault(t => t.Name == name); .FirstOrDefault(t => t.Name == name);
} }
[Obsolete("Use FindAsync method.")] [Obsolete("Use FindAsync method.")]
public virtual Tenant FindById(Guid id, bool includeDetails = true) public virtual Tenant FindById(Guid id, bool includeDetails = true)
{ {
return GetMongoQueryable() return GetMongoQueryable()
.FirstOrDefault(t => t.Id == id); .FirstOrDefault(t => t.Id == id);
} }
public virtual async Task<List<Tenant>> GetListAsync( public virtual async Task<List<Tenant>> GetListAsync(
string sorting = null, string sorting = null,
int maxResultCount = int.MaxValue, int maxResultCount = int.MaxValue,
int skipCount = 0, int skipCount = 0,
string filter = null, string filter = null,
bool includeDetails = false, bool includeDetails = false,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
return await (await GetMongoQueryableAsync(cancellationToken)) return await (await GetMongoQueryableAsync(cancellationToken))
.WhereIf<Tenant, IMongoQueryable<Tenant>>( .WhereIf<Tenant, IMongoQueryable<Tenant>>(
!filter.IsNullOrWhiteSpace(), !filter.IsNullOrWhiteSpace(),
u => u =>
u.Name.Contains(filter) u.Name.Contains(filter)
) )
.OrderBy(sorting.IsNullOrEmpty() ? nameof(Tenant.Name) : sorting) .OrderBy(sorting.IsNullOrEmpty() ? nameof(Tenant.Name) : sorting)
.As<IMongoQueryable<Tenant>>() .As<IMongoQueryable<Tenant>>()
.PageBy<Tenant, IMongoQueryable<Tenant>>(skipCount, maxResultCount) .PageBy<Tenant, IMongoQueryable<Tenant>>(skipCount, maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken)); .ToListAsync(GetCancellationToken(cancellationToken));
} }
public virtual async Task<long> GetCountAsync(string filter = null, CancellationToken cancellationToken = default) public virtual async Task<long> GetCountAsync(string filter = null, CancellationToken cancellationToken = default)
{ {
return await (await GetMongoQueryableAsync(cancellationToken)) return await (await GetMongoQueryableAsync(cancellationToken))
.WhereIf<Tenant, IMongoQueryable<Tenant>>( .WhereIf<Tenant, IMongoQueryable<Tenant>>(
!filter.IsNullOrWhiteSpace(), !filter.IsNullOrWhiteSpace(),
u => u =>
u.Name.Contains(filter) u.Name.Contains(filter)
).CountAsync(cancellationToken: cancellationToken); ).CountAsync(cancellationToken: cancellationToken);
}
} }
} }

21
modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/TenantManagementMongoDbContext.cs

@ -3,19 +3,18 @@ using Volo.Abp.Data;
using Volo.Abp.MongoDB; using Volo.Abp.MongoDB;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
namespace Volo.Abp.TenantManagement.MongoDB namespace Volo.Abp.TenantManagement.MongoDB;
[IgnoreMultiTenancy]
[ConnectionStringName(AbpTenantManagementDbProperties.ConnectionStringName)]
public class TenantManagementMongoDbContext : AbpMongoDbContext, ITenantManagementMongoDbContext
{ {
[IgnoreMultiTenancy] public IMongoCollection<Tenant> Tenants => Collection<Tenant>();
[ConnectionStringName(AbpTenantManagementDbProperties.ConnectionStringName)]
public class TenantManagementMongoDbContext : AbpMongoDbContext, ITenantManagementMongoDbContext
{
public IMongoCollection<Tenant> Tenants => Collection<Tenant>();
protected override void CreateModel(IMongoModelBuilder modelBuilder) protected override void CreateModel(IMongoModelBuilder modelBuilder)
{ {
base.CreateModel(modelBuilder); base.CreateModel(modelBuilder);
modelBuilder.ConfigureTenantManagement(); modelBuilder.ConfigureTenantManagement();
}
} }
} }

25
modules/tenant-management/src/Volo.Abp.TenantManagement.Web/AbpTenantManagementWebAutoMapperProfile.cs

@ -2,22 +2,21 @@
using Volo.Abp.AutoMapper; using Volo.Abp.AutoMapper;
using Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants; using Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants;
namespace Volo.Abp.TenantManagement.Web namespace Volo.Abp.TenantManagement.Web;
public class AbpTenantManagementWebAutoMapperProfile : Profile
{ {
public class AbpTenantManagementWebAutoMapperProfile : Profile public AbpTenantManagementWebAutoMapperProfile()
{ {
public AbpTenantManagementWebAutoMapperProfile() //List
{ CreateMap<TenantDto, EditModalModel.TenantInfoModel>();
//List
CreateMap<TenantDto, EditModalModel.TenantInfoModel>();
//CreateModal //CreateModal
CreateMap<CreateModalModel.TenantInfoModel, TenantCreateDto>() CreateMap<CreateModalModel.TenantInfoModel, TenantCreateDto>()
.MapExtraProperties(); .MapExtraProperties();
//EditModal //EditModal
CreateMap<EditModalModel.TenantInfoModel, TenantUpdateDto>() CreateMap<EditModalModel.TenantInfoModel, TenantUpdateDto>()
.MapExtraProperties(); .MapExtraProperties();
}
} }
} }

149
modules/tenant-management/src/Volo.Abp.TenantManagement.Web/AbpTenantManagementWebModule.cs

@ -16,94 +16,93 @@ using Volo.Abp.UI.Navigation;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
using Volo.Abp.Threading; using Volo.Abp.Threading;
namespace Volo.Abp.TenantManagement.Web namespace Volo.Abp.TenantManagement.Web;
[DependsOn(typeof(AbpTenantManagementApplicationContractsModule))]
[DependsOn(typeof(AbpAspNetCoreMvcUiBootstrapModule))]
[DependsOn(typeof(AbpFeatureManagementWebModule))]
[DependsOn(typeof(AbpAutoMapperModule))]
public class AbpTenantManagementWebModule : AbpModule
{ {
[DependsOn(typeof(AbpTenantManagementApplicationContractsModule))] private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
[DependsOn(typeof(AbpAspNetCoreMvcUiBootstrapModule))]
[DependsOn(typeof(AbpFeatureManagementWebModule))]
[DependsOn(typeof(AbpAutoMapperModule))]
public class AbpTenantManagementWebModule : AbpModule
{
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
public override void PreConfigureServices(ServiceConfigurationContext context) public override void PreConfigureServices(ServiceConfigurationContext context)
{
context.Services.PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options =>
{ {
context.Services.PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options => options.AddAssemblyResource(typeof(AbpTenantManagementResource), typeof(AbpTenantManagementWebModule).Assembly);
{ });
options.AddAssemblyResource(typeof(AbpTenantManagementResource), typeof(AbpTenantManagementWebModule).Assembly);
});
PreConfigure<IMvcBuilder>(mvcBuilder => PreConfigure<IMvcBuilder>(mvcBuilder =>
{ {
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpTenantManagementWebModule).Assembly); mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpTenantManagementWebModule).Assembly);
}); });
} }
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpNavigationOptions>(options =>
{ {
Configure<AbpNavigationOptions>(options => options.MenuContributors.Add(new AbpTenantManagementWebMainMenuContributor());
{ });
options.MenuContributors.Add(new AbpTenantManagementWebMainMenuContributor());
});
Configure<AbpVirtualFileSystemOptions>(options => Configure<AbpVirtualFileSystemOptions>(options =>
{ {
options.FileSets.AddEmbedded<AbpTenantManagementWebModule>(); options.FileSets.AddEmbedded<AbpTenantManagementWebModule>();
}); });
context.Services.AddAutoMapperObjectMapper<AbpTenantManagementWebModule>(); context.Services.AddAutoMapperObjectMapper<AbpTenantManagementWebModule>();
Configure<AbpAutoMapperOptions>(options => Configure<AbpAutoMapperOptions>(options =>
{ {
options.AddProfile<AbpTenantManagementWebAutoMapperProfile>(validate: true); options.AddProfile<AbpTenantManagementWebAutoMapperProfile>(validate: true);
}); });
Configure<RazorPagesOptions>(options => Configure<RazorPagesOptions>(options =>
{ {
options.Conventions.AuthorizePage("/TenantManagement/Tenants/Index", TenantManagementPermissions.Tenants.Default); options.Conventions.AuthorizePage("/TenantManagement/Tenants/Index", TenantManagementPermissions.Tenants.Default);
options.Conventions.AuthorizePage("/TenantManagement/Tenants/CreateModal", TenantManagementPermissions.Tenants.Create); options.Conventions.AuthorizePage("/TenantManagement/Tenants/CreateModal", TenantManagementPermissions.Tenants.Create);
options.Conventions.AuthorizePage("/TenantManagement/Tenants/EditModal", TenantManagementPermissions.Tenants.Update); options.Conventions.AuthorizePage("/TenantManagement/Tenants/EditModal", TenantManagementPermissions.Tenants.Update);
}); });
Configure<AbpPageToolbarOptions>(options => Configure<AbpPageToolbarOptions>(options =>
{ {
options.Configure<Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants.IndexModel>( options.Configure<Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants.IndexModel>(
toolbar => toolbar =>
{ {
toolbar.AddButton( toolbar.AddButton(
LocalizableString.Create<AbpTenantManagementResource>("ManageHostFeatures"), LocalizableString.Create<AbpTenantManagementResource>("ManageHostFeatures"),
icon: "cog", icon: "cog",
name: "ManageHostFeatures", name: "ManageHostFeatures",
requiredPolicyName: FeatureManagementPermissions.ManageHostFeatures requiredPolicyName: FeatureManagementPermissions.ManageHostFeatures
); );
toolbar.AddButton( toolbar.AddButton(
LocalizableString.Create<AbpTenantManagementResource>("NewTenant"), LocalizableString.Create<AbpTenantManagementResource>("NewTenant"),
icon: "plus", icon: "plus",
name: "CreateTenant", name: "CreateTenant",
requiredPolicyName: TenantManagementPermissions.Tenants.Create requiredPolicyName: TenantManagementPermissions.Tenants.Create
); );
} }
); );
}); });
Configure<DynamicJavaScriptProxyOptions>(options => Configure<DynamicJavaScriptProxyOptions>(options =>
{ {
options.DisableModule(TenantManagementRemoteServiceConsts.ModuleName); options.DisableModule(TenantManagementRemoteServiceConsts.ModuleName);
}); });
} }
public override void PostConfigureServices(ServiceConfigurationContext context) public override void PostConfigureServices(ServiceConfigurationContext context)
{
OneTimeRunner.Run(() =>
{ {
OneTimeRunner.Run(() => ModuleExtensionConfigurationHelper
{ .ApplyEntityConfigurationToUi(
ModuleExtensionConfigurationHelper TenantManagementModuleExtensionConsts.ModuleName,
.ApplyEntityConfigurationToUi( TenantManagementModuleExtensionConsts.EntityNames.Tenant,
TenantManagementModuleExtensionConsts.ModuleName, createFormTypes: new[] { typeof(Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants.CreateModalModel.TenantInfoModel) },
TenantManagementModuleExtensionConsts.EntityNames.Tenant, editFormTypes: new[] { typeof(Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants.EditModalModel.TenantInfoModel) }
createFormTypes: new[] { typeof(Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants.CreateModalModel.TenantInfoModel) }, );
editFormTypes: new[] { typeof(Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants.EditModalModel.TenantInfoModel) } });
);
});
}
} }
} }

27
modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Navigation/AbpTenantManagementWebMainMenuContributor.cs

@ -6,27 +6,26 @@ using Volo.Abp.TenantManagement.Localization;
using Volo.Abp.UI.Navigation; using Volo.Abp.UI.Navigation;
using Volo.Abp.Authorization.Permissions; using Volo.Abp.Authorization.Permissions;
namespace Volo.Abp.TenantManagement.Web.Navigation namespace Volo.Abp.TenantManagement.Web.Navigation;
public class AbpTenantManagementWebMainMenuContributor : IMenuContributor
{ {
public class AbpTenantManagementWebMainMenuContributor : IMenuContributor public virtual Task ConfigureMenuAsync(MenuConfigurationContext context)
{ {
public virtual Task ConfigureMenuAsync(MenuConfigurationContext context) if (context.Menu.Name != StandardMenus.Main)
{ {
if (context.Menu.Name != StandardMenus.Main) return Task.CompletedTask;
{ }
return Task.CompletedTask;
}
var administrationMenu = context.Menu.GetAdministration(); var administrationMenu = context.Menu.GetAdministration();
var l = context.GetLocalizer<AbpTenantManagementResource>(); var l = context.GetLocalizer<AbpTenantManagementResource>();
var tenantManagementMenuItem = new ApplicationMenuItem(TenantManagementMenuNames.GroupName, l["Menu:TenantManagement"], icon: "fa fa-users"); var tenantManagementMenuItem = new ApplicationMenuItem(TenantManagementMenuNames.GroupName, l["Menu:TenantManagement"], icon: "fa fa-users");
administrationMenu.AddItem(tenantManagementMenuItem); administrationMenu.AddItem(tenantManagementMenuItem);
tenantManagementMenuItem.AddItem(new ApplicationMenuItem(TenantManagementMenuNames.Tenants, l["Tenants"], url: "~/TenantManagement/Tenants").RequirePermissions(TenantManagementPermissions.Tenants.Default)); tenantManagementMenuItem.AddItem(new ApplicationMenuItem(TenantManagementMenuNames.Tenants, l["Tenants"], url: "~/TenantManagement/Tenants").RequirePermissions(TenantManagementPermissions.Tenants.Default));
return Task.CompletedTask; return Task.CompletedTask;
}
} }
} }

11
modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Navigation/TenantManagementMenuNames.cs

@ -1,9 +1,8 @@
namespace Volo.Abp.TenantManagement.Web.Navigation namespace Volo.Abp.TenantManagement.Web.Navigation;
public class TenantManagementMenuNames
{ {
public class TenantManagementMenuNames public const string GroupName = "TenantManagement";
{
public const string GroupName = "TenantManagement";
public const string Tenants = GroupName + ".Tenants"; public const string Tenants = GroupName + ".Tenants";
}
} }

89
modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/CreateModal.cshtml.cs

@ -4,52 +4,51 @@ using Microsoft.AspNetCore.Mvc;
using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectExtending;
using Volo.Abp.Validation; using Volo.Abp.Validation;
namespace Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants namespace Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants;
public class CreateModalModel : TenantManagementPageModel
{ {
public class CreateModalModel : TenantManagementPageModel [BindProperty]
public TenantInfoModel Tenant { get; set; }
protected ITenantAppService TenantAppService { get; }
public CreateModalModel(ITenantAppService tenantAppService)
{
TenantAppService = tenantAppService;
}
public virtual Task<IActionResult> OnGetAsync()
{
Tenant = new TenantInfoModel();
return Task.FromResult<IActionResult>(Page());
}
public virtual async Task<IActionResult> OnPostAsync()
{
ValidateModel();
var input = ObjectMapper.Map<TenantInfoModel, TenantCreateDto>(Tenant);
await TenantAppService.CreateAsync(input);
return NoContent();
}
public class TenantInfoModel : ExtensibleObject
{ {
[BindProperty] [Required]
public TenantInfoModel Tenant { get; set; } [DynamicStringLength(typeof(TenantConsts), nameof(TenantConsts.MaxNameLength))]
[Display(Name = "DisplayName:TenantName")]
protected ITenantAppService TenantAppService { get; } public string Name { get; set; }
public CreateModalModel(ITenantAppService tenantAppService) [Required]
{ [EmailAddress]
TenantAppService = tenantAppService; [MaxLength(256)]
} public string AdminEmailAddress { get; set; }
public virtual Task<IActionResult> OnGetAsync() [Required]
{ [DataType(DataType.Password)]
Tenant = new TenantInfoModel(); [MaxLength(128)]
return Task.FromResult<IActionResult>(Page()); public string AdminPassword { get; set; }
}
public virtual async Task<IActionResult> OnPostAsync()
{
ValidateModel();
var input = ObjectMapper.Map<TenantInfoModel, TenantCreateDto>(Tenant);
await TenantAppService.CreateAsync(input);
return NoContent();
}
public class TenantInfoModel: ExtensibleObject
{
[Required]
[DynamicStringLength(typeof(TenantConsts), nameof(TenantConsts.MaxNameLength))]
[Display(Name = "DisplayName:TenantName")]
public string Name { get; set; }
[Required]
[EmailAddress]
[MaxLength(256)]
public string AdminEmailAddress { get; set; }
[Required]
[DataType(DataType.Password)]
[MaxLength(128)]
public string AdminPassword { get; set; }
}
} }
} }

71
modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/EditModal.cshtml.cs

@ -6,51 +6,50 @@ using Volo.Abp.Domain.Entities;
using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectExtending;
using Volo.Abp.Validation; using Volo.Abp.Validation;
namespace Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants namespace Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants;
public class EditModalModel : TenantManagementPageModel
{ {
public class EditModalModel : TenantManagementPageModel [BindProperty]
{ public TenantInfoModel Tenant { get; set; }
[BindProperty]
public TenantInfoModel Tenant { get; set; }
protected ITenantAppService TenantAppService { get; } protected ITenantAppService TenantAppService { get; }
public EditModalModel(ITenantAppService tenantAppService) public EditModalModel(ITenantAppService tenantAppService)
{ {
TenantAppService = tenantAppService; TenantAppService = tenantAppService;
} }
public virtual async Task<IActionResult> OnGetAsync(Guid id) public virtual async Task<IActionResult> OnGetAsync(Guid id)
{ {
Tenant = ObjectMapper.Map<TenantDto, TenantInfoModel>( Tenant = ObjectMapper.Map<TenantDto, TenantInfoModel>(
await TenantAppService.GetAsync(id) await TenantAppService.GetAsync(id)
); );
return Page(); return Page();
} }
public virtual async Task<IActionResult> OnPostAsync() public virtual async Task<IActionResult> OnPostAsync()
{ {
ValidateModel(); ValidateModel();
var input = ObjectMapper.Map<TenantInfoModel, TenantUpdateDto>(Tenant); var input = ObjectMapper.Map<TenantInfoModel, TenantUpdateDto>(Tenant);
await TenantAppService.UpdateAsync(Tenant.Id, input); await TenantAppService.UpdateAsync(Tenant.Id, input);
return NoContent(); return NoContent();
} }
public class TenantInfoModel : ExtensibleObject, IHasConcurrencyStamp public class TenantInfoModel : ExtensibleObject, IHasConcurrencyStamp
{ {
[HiddenInput] [HiddenInput]
public Guid Id { get; set; } public Guid Id { get; set; }
[Required] [Required]
[DynamicStringLength(typeof(TenantConsts), nameof(TenantConsts.MaxNameLength))] [DynamicStringLength(typeof(TenantConsts), nameof(TenantConsts.MaxNameLength))]
[Display(Name = "DisplayName:TenantName")] [Display(Name = "DisplayName:TenantName")]
public string Name { get; set; } public string Name { get; set; }
[HiddenInput] [HiddenInput]
public string ConcurrencyStamp { get; set; } public string ConcurrencyStamp { get; set; }
}
} }
} }

21
modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.cshtml.cs

@ -2,18 +2,17 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants namespace Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants;
public class IndexModel : TenantManagementPageModel
{ {
public class IndexModel : TenantManagementPageModel public virtual Task<IActionResult> OnGetAsync()
{ {
public virtual Task<IActionResult> OnGetAsync() return Task.FromResult<IActionResult>(Page());
{ }
return Task.FromResult<IActionResult>(Page());
}
public virtual Task<IActionResult> OnPostAsync() public virtual Task<IActionResult> OnPostAsync()
{ {
return Task.FromResult<IActionResult>(Page()); return Task.FromResult<IActionResult>(Page());
}
} }
} }

13
modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/TenantManagementPageModel.cs

@ -1,12 +1,11 @@
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
namespace Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants namespace Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants;
public abstract class TenantManagementPageModel : AbpPageModel
{ {
public abstract class TenantManagementPageModel : AbpPageModel public TenantManagementPageModel()
{ {
public TenantManagementPageModel() ObjectMapperContext = typeof(AbpTenantManagementWebModule);
{
ObjectMapperContext = typeof(AbpTenantManagementWebModule);
}
} }
} }

23
modules/tenant-management/test/Volo.Abp.TenantManagement.Application.Tests/Volo/Abp/TenantManagement/AbpTenantManagementApplicationTestBase.cs

@ -1,24 +1,23 @@
using System; using System;
using Volo.Abp.TenantManagement.EntityFrameworkCore; using Volo.Abp.TenantManagement.EntityFrameworkCore;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public abstract class AbpTenantManagementApplicationTestBase : TenantManagementTestBase<AbpTenantManagementApplicationTestModule>
{ {
public abstract class AbpTenantManagementApplicationTestBase : TenantManagementTestBase<AbpTenantManagementApplicationTestModule> protected virtual void UsingDbContext(Action<ITenantManagementDbContext> action)
{ {
protected virtual void UsingDbContext(Action<ITenantManagementDbContext> action) using (var dbContext = GetRequiredService<ITenantManagementDbContext>())
{ {
using (var dbContext = GetRequiredService<ITenantManagementDbContext>()) action.Invoke(dbContext);
{
action.Invoke(dbContext);
}
} }
}
protected virtual T UsingDbContext<T>(Func<ITenantManagementDbContext, T> action) protected virtual T UsingDbContext<T>(Func<ITenantManagementDbContext, T> action)
{
using (var dbContext = GetRequiredService<ITenantManagementDbContext>())
{ {
using (var dbContext = GetRequiredService<ITenantManagementDbContext>()) return action.Invoke(dbContext);
{
return action.Invoke(dbContext);
}
} }
} }
} }

17
modules/tenant-management/test/Volo.Abp.TenantManagement.Application.Tests/Volo/Abp/TenantManagement/AbpTenantManagementApplicationTestModule.cs

@ -2,16 +2,15 @@
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.TenantManagement.EntityFrameworkCore; using Volo.Abp.TenantManagement.EntityFrameworkCore;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
[DependsOn(
typeof(AbpTenantManagementApplicationModule),
typeof(AbpTenantManagementEntityFrameworkCoreTestModule))]
public class AbpTenantManagementApplicationTestModule : AbpModule
{ {
[DependsOn( public override void ConfigureServices(ServiceConfigurationContext context)
typeof(AbpTenantManagementApplicationModule),
typeof(AbpTenantManagementEntityFrameworkCoreTestModule))]
public class AbpTenantManagementApplicationTestModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) context.Services.AddAlwaysAllowAuthorization();
{
context.Services.AddAlwaysAllowAuthorization();
}
} }
} }

173
modules/tenant-management/test/Volo.Abp.TenantManagement.Application.Tests/Volo/Abp/TenantManagement/TenantAppService_Tests.cs

@ -4,109 +4,108 @@ using System.Threading.Tasks;
using Shouldly; using Shouldly;
using Xunit; using Xunit;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class TenantAppService_Tests : AbpTenantManagementApplicationTestBase
{ {
public class TenantAppService_Tests : AbpTenantManagementApplicationTestBase private readonly ITenantAppService _tenantAppService;
public TenantAppService_Tests()
{ {
private readonly ITenantAppService _tenantAppService; _tenantAppService = GetRequiredService<ITenantAppService>();
}
public TenantAppService_Tests() [Fact]
{ public async Task GetAsync()
_tenantAppService = GetRequiredService<ITenantAppService>(); {
} var tenantInDb = UsingDbContext(dbContext => dbContext.Tenants.First());
var tenant = await _tenantAppService.GetAsync(tenantInDb.Id);
tenant.Name.ShouldBe(tenantInDb.Name);
}
[Fact] [Fact]
public async Task GetAsync() public async Task GetListAsync()
{ {
var tenantInDb = UsingDbContext(dbContext => dbContext.Tenants.First()); var result = await _tenantAppService.GetListAsync(new GetTenantsInput());
var tenant = await _tenantAppService.GetAsync(tenantInDb.Id); result.TotalCount.ShouldBeGreaterThan(0);
tenant.Name.ShouldBe(tenantInDb.Name); result.Items.ShouldContain(t => t.Name == "acme");
} result.Items.ShouldContain(t => t.Name == "volosoft");
}
[Fact] [Fact]
public async Task GetListAsync() public async Task GetListAsync_Filtered()
{ {
var result = await _tenantAppService.GetListAsync(new GetTenantsInput()); var result = await _tenantAppService.GetListAsync(new GetTenantsInput { Filter = "volo" });
result.TotalCount.ShouldBeGreaterThan(0); result.TotalCount.ShouldBeGreaterThan(0);
result.Items.ShouldContain(t => t.Name == "acme"); result.Items.ShouldNotContain(t => t.Name == "acme");
result.Items.ShouldContain(t => t.Name == "volosoft"); result.Items.ShouldContain(t => t.Name == "volosoft");
} }
[Fact]
public async Task GetListAsync_Filtered()
{
var result = await _tenantAppService.GetListAsync(new GetTenantsInput { Filter = "volo" });
result.TotalCount.ShouldBeGreaterThan(0);
result.Items.ShouldNotContain(t => t.Name == "acme");
result.Items.ShouldContain(t => t.Name == "volosoft");
}
[Fact]
public async Task GetListAsync_Sorted_Descending_By_Name()
{
var result = await _tenantAppService.GetListAsync(new GetTenantsInput { Sorting = "Name DESC" });
result.TotalCount.ShouldBeGreaterThan(0);
var tenants = result.Items.ToList();
tenants.ShouldContain(t => t.Name == "acme"); [Fact]
tenants.ShouldContain(t => t.Name == "volosoft"); public async Task GetListAsync_Sorted_Descending_By_Name()
{
var result = await _tenantAppService.GetListAsync(new GetTenantsInput { Sorting = "Name DESC" });
result.TotalCount.ShouldBeGreaterThan(0);
var tenants = result.Items.ToList();
tenants.FindIndex(t => t.Name == "acme").ShouldBeGreaterThan(tenants.FindIndex(t => t.Name == "volosoft")); tenants.ShouldContain(t => t.Name == "acme");
} tenants.ShouldContain(t => t.Name == "volosoft");
[Fact] tenants.FindIndex(t => t.Name == "acme").ShouldBeGreaterThan(tenants.FindIndex(t => t.Name == "volosoft"));
public async Task CreateAsync() }
{
var tenancyName = Guid.NewGuid().ToString("N").ToLowerInvariant(); [Fact]
var tenant = await _tenantAppService.CreateAsync(new TenantCreateDto { Name = tenancyName , AdminEmailAddress = "admin@admin.com", AdminPassword = "123456"}); public async Task CreateAsync()
tenant.Name.ShouldBe(tenancyName); {
tenant.Id.ShouldNotBe(default(Guid)); var tenancyName = Guid.NewGuid().ToString("N").ToLowerInvariant();
} var tenant = await _tenantAppService.CreateAsync(new TenantCreateDto { Name = tenancyName, AdminEmailAddress = "admin@admin.com", AdminPassword = "123456" });
tenant.Name.ShouldBe(tenancyName);
[Fact] tenant.Id.ShouldNotBe(default(Guid));
public async Task CreateAsync_Should_Not_Allow_Duplicate_Names() }
{
await Assert.ThrowsAsync<UserFriendlyException>(async () => [Fact]
{ public async Task CreateAsync_Should_Not_Allow_Duplicate_Names()
await _tenantAppService.CreateAsync(new TenantCreateDto { Name = "acme", AdminEmailAddress = "admin@admin.com", AdminPassword = "123456" }); {
}); await Assert.ThrowsAsync<UserFriendlyException>(async () =>
}
[Fact]
public async Task UpdateAsync()
{ {
var acme = UsingDbContext(dbContext => dbContext.Tenants.Single(t => t.Name == "acme")); await _tenantAppService.CreateAsync(new TenantCreateDto { Name = "acme", AdminEmailAddress = "admin@admin.com", AdminPassword = "123456" });
});
}
var result = await _tenantAppService.UpdateAsync(acme.Id, new TenantUpdateDto { Name = "acme-renamed" }); [Fact]
result.Id.ShouldBe(acme.Id); public async Task UpdateAsync()
result.Name.ShouldBe("acme-renamed"); {
var acme = UsingDbContext(dbContext => dbContext.Tenants.Single(t => t.Name == "acme"));
var acmeUpdated = UsingDbContext(dbContext => dbContext.Tenants.Single(t => t.Id == acme.Id)); var result = await _tenantAppService.UpdateAsync(acme.Id, new TenantUpdateDto { Name = "acme-renamed" });
acmeUpdated.Name.ShouldBe("acme-renamed"); result.Id.ShouldBe(acme.Id);
} result.Name.ShouldBe("acme-renamed");
[Fact] var acmeUpdated = UsingDbContext(dbContext => dbContext.Tenants.Single(t => t.Id == acme.Id));
public async Task UpdateAsync_Should_Not_Allow_Duplicate_Names() acmeUpdated.Name.ShouldBe("acme-renamed");
{ }
var acme = UsingDbContext(dbContext => dbContext.Tenants.Single(t => t.Name == "acme"));
await Assert.ThrowsAsync<UserFriendlyException>(async () => [Fact]
{ public async Task UpdateAsync_Should_Not_Allow_Duplicate_Names()
await _tenantAppService.UpdateAsync(acme.Id, new TenantUpdateDto { Name = "volosoft" }); {
}); var acme = UsingDbContext(dbContext => dbContext.Tenants.Single(t => t.Name == "acme"));
}
[Fact] await Assert.ThrowsAsync<UserFriendlyException>(async () =>
public async Task DeleteAsync()
{ {
var acme = UsingDbContext(dbContext => dbContext.Tenants.Single(t => t.Name == "acme")); await _tenantAppService.UpdateAsync(acme.Id, new TenantUpdateDto { Name = "volosoft" });
});
}
[Fact]
public async Task DeleteAsync()
{
var acme = UsingDbContext(dbContext => dbContext.Tenants.Single(t => t.Name == "acme"));
await _tenantAppService.DeleteAsync(acme.Id); await _tenantAppService.DeleteAsync(acme.Id);
UsingDbContext(dbContext => UsingDbContext(dbContext =>
{ {
dbContext.Tenants.Any(t => t.Id == acme.Id).ShouldBeFalse(); dbContext.Tenants.Any(t => t.Id == acme.Id).ShouldBeFalse();
}); });
}
} }
} }

13
modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/AbpSettingManagementDomainTestModule.cs

@ -1,13 +1,12 @@
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.TenantManagement.EntityFrameworkCore; using Volo.Abp.TenantManagement.EntityFrameworkCore;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
[DependsOn(
typeof(AbpTenantManagementEntityFrameworkCoreTestModule),
typeof(AbpTenantManagementTestBaseModule))]
public class AbpSettingManagementDomainTestModule : AbpModule
{ {
[DependsOn(
typeof(AbpTenantManagementEntityFrameworkCoreTestModule),
typeof(AbpTenantManagementTestBaseModule))]
public class AbpSettingManagementDomainTestModule : AbpModule
{
}
} }

7
modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/AbpTenantManagementDomainTestBase.cs

@ -2,10 +2,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class AbpTenantManagementDomainTestBase : TenantManagementTestBase<AbpSettingManagementDomainTestModule>
{ {
public class AbpTenantManagementDomainTestBase : TenantManagementTestBase<AbpSettingManagementDomainTestModule>
{
}
} }

45
modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/Localization_Tests.cs

@ -5,37 +5,36 @@ using Volo.Abp.Localization;
using Volo.Abp.TenantManagement.Localization; using Volo.Abp.TenantManagement.Localization;
using Xunit; using Xunit;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class Localization_Tests : AbpTenantManagementDomainTestBase
{ {
public class Localization_Tests : AbpTenantManagementDomainTestBase private readonly IStringLocalizer<AbpTenantManagementResource> _stringLocalizer;
public Localization_Tests()
{ {
private readonly IStringLocalizer<AbpTenantManagementResource> _stringLocalizer; _stringLocalizer = GetRequiredService<IStringLocalizer<AbpTenantManagementResource>>();
}
public Localization_Tests() [Fact]
public void Test()
{
using (CultureHelper.Use("en"))
{ {
_stringLocalizer = GetRequiredService<IStringLocalizer<AbpTenantManagementResource>>(); _stringLocalizer["TenantDeletionConfirmationMessage"].Value
.ShouldBe("Tenant '{0}' will be deleted. Do you confirm that?");
} }
[Fact] using (CultureHelper.Use("en-gb"))
public void Test()
{ {
using (CultureHelper.Use("en")) _stringLocalizer["TenantDeletionConfirmationMessage"].Value
{ .ShouldBe("Tenant '{0}' will be deleted. Is that OK?");
_stringLocalizer["TenantDeletionConfirmationMessage"].Value }
.ShouldBe("Tenant '{0}' will be deleted. Do you confirm that?");
}
using (CultureHelper.Use("en-gb"))
{
_stringLocalizer["TenantDeletionConfirmationMessage"].Value
.ShouldBe("Tenant '{0}' will be deleted. Is that OK?");
}
using (CultureHelper.Use("tr")) using (CultureHelper.Use("tr"))
{ {
_stringLocalizer["TenantDeletionConfirmationMessage"].Value _stringLocalizer["TenantDeletionConfirmationMessage"].Value
.ShouldBe("'{0}' isimli müşteri silinecektir. Onaylıyor musunuz?"); .ShouldBe("'{0}' isimli müşteri silinecektir. Onaylıyor musunuz?");
}
} }
} }
} }

111
modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantCacheItemInvalidator_Tests.cs

@ -4,83 +4,82 @@ using Volo.Abp.Caching;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Xunit; using Xunit;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class TenantCacheItemInvalidator_Tests : AbpTenantManagementDomainTestBase
{ {
public class TenantCacheItemInvalidator_Tests : AbpTenantManagementDomainTestBase private readonly IDistributedCache<TenantCacheItem> _cache;
{ private readonly ITenantStore _tenantStore;
private readonly IDistributedCache<TenantCacheItem> _cache; private readonly ITenantRepository _tenantRepository;
private readonly ITenantStore _tenantStore;
private readonly ITenantRepository _tenantRepository;
public TenantCacheItemInvalidator_Tests() public TenantCacheItemInvalidator_Tests()
{ {
_cache = GetRequiredService<IDistributedCache<TenantCacheItem>>(); _cache = GetRequiredService<IDistributedCache<TenantCacheItem>>();
_tenantStore = GetRequiredService<ITenantStore>(); _tenantStore = GetRequiredService<ITenantStore>();
_tenantRepository = GetRequiredService<ITenantRepository>(); _tenantRepository = GetRequiredService<ITenantRepository>();
} }
[Fact] [Fact]
public async Task Get_Tenant_Should_Cached() public async Task Get_Tenant_Should_Cached()
{ {
var acme = await _tenantRepository.FindByNameAsync("acme"); var acme = await _tenantRepository.FindByNameAsync("acme");
acme.ShouldNotBeNull(); acme.ShouldNotBeNull();
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(acme.Id, null))).ShouldBeNull(); (await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(acme.Id, null))).ShouldBeNull();
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(null, acme.Name))).ShouldBeNull(); (await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(null, acme.Name))).ShouldBeNull();
await _tenantStore.FindAsync(acme.Id); await _tenantStore.FindAsync(acme.Id);
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(acme.Id, null))).ShouldNotBeNull(); (await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(acme.Id, null))).ShouldNotBeNull();
await _tenantStore.FindAsync(acme.Name); await _tenantStore.FindAsync(acme.Name);
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(null, acme.Name))).ShouldNotBeNull(); (await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(null, acme.Name))).ShouldNotBeNull();
var volosoft = _tenantRepository.FindByName("volosoft"); var volosoft = _tenantRepository.FindByName("volosoft");
volosoft.ShouldNotBeNull(); volosoft.ShouldNotBeNull();
(_cache.Get(TenantCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldBeNull(); (_cache.Get(TenantCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldBeNull();
(_cache.Get(TenantCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldBeNull(); (_cache.Get(TenantCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldBeNull();
_tenantStore.Find(volosoft.Id); _tenantStore.Find(volosoft.Id);
(_cache.Get(TenantCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldNotBeNull(); (_cache.Get(TenantCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldNotBeNull();
_tenantStore.Find(volosoft.Name); _tenantStore.Find(volosoft.Name);
(_cache.Get(TenantCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldNotBeNull(); (_cache.Get(TenantCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldNotBeNull();
} }
[Fact] [Fact]
public async Task Cache_Should_Invalidator_When_Tenant_Changed() public async Task Cache_Should_Invalidator_When_Tenant_Changed()
{ {
var acme = await _tenantRepository.FindByNameAsync("acme"); var acme = await _tenantRepository.FindByNameAsync("acme");
acme.ShouldNotBeNull(); acme.ShouldNotBeNull();
// FindAsync will cache tenant. // FindAsync will cache tenant.
await _tenantStore.FindAsync(acme.Id); await _tenantStore.FindAsync(acme.Id);
await _tenantStore.FindAsync(acme.Name); await _tenantStore.FindAsync(acme.Name);
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(acme.Id, null))).ShouldNotBeNull(); (await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(acme.Id, null))).ShouldNotBeNull();
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(null, acme.Name))).ShouldNotBeNull(); (await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(null, acme.Name))).ShouldNotBeNull();
await _tenantRepository.DeleteAsync(acme); await _tenantRepository.DeleteAsync(acme);
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(acme.Id, null))).ShouldBeNull(); (await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(acme.Id, null))).ShouldBeNull();
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(null, acme.Name))).ShouldBeNull(); (await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(null, acme.Name))).ShouldBeNull();
var volosoft = await _tenantRepository.FindByNameAsync("volosoft"); var volosoft = await _tenantRepository.FindByNameAsync("volosoft");
volosoft.ShouldNotBeNull(); volosoft.ShouldNotBeNull();
// Find will cache tenant. // Find will cache tenant.
_tenantStore.Find(volosoft.Id); _tenantStore.Find(volosoft.Id);
_tenantStore.Find(volosoft.Name); _tenantStore.Find(volosoft.Name);
(_cache.Get(TenantCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldNotBeNull(); (_cache.Get(TenantCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldNotBeNull();
(_cache.Get(TenantCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldNotBeNull(); (_cache.Get(TenantCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldNotBeNull();
await _tenantRepository.DeleteAsync(volosoft); await _tenantRepository.DeleteAsync(volosoft);
(_cache.Get(TenantCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldBeNull(); (_cache.Get(TenantCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldBeNull();
(_cache.Get(TenantCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldBeNull(); (_cache.Get(TenantCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldBeNull();
}
} }
} }

23
modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantConnectionString_Tests.cs

@ -3,19 +3,18 @@ using System.Threading.Tasks;
using Shouldly; using Shouldly;
using Xunit; using Xunit;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class TenantConnectionString_Tests
{ {
public class TenantConnectionString_Tests [Theory]
[InlineData("aaa")]
[InlineData("bbb")]
public void SetValue(string value)
{ {
[Theory] var tenantConnectionString =
[InlineData("aaa")] new TenantConnectionString(Guid.NewGuid(), "MyConnString", "MyConnString-Value");
[InlineData("bbb")] tenantConnectionString.SetValue(value);
public void SetValue(string value) tenantConnectionString.Value.ShouldBe(value);
{
var tenantConnectionString =
new TenantConnectionString(Guid.NewGuid(), "MyConnString", "MyConnString-Value");
tenantConnectionString.SetValue(value);
tenantConnectionString.Value.ShouldBe(value);
}
} }
} }

87
modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantManager_Tests.cs

@ -2,51 +2,50 @@
using Shouldly; using Shouldly;
using Xunit; using Xunit;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class TenantManager_Tests : AbpTenantManagementDomainTestBase
{ {
public class TenantManager_Tests : AbpTenantManagementDomainTestBase private readonly ITenantManager _tenantManager;
private readonly ITenantRepository _tenantRepository;
public TenantManager_Tests()
{
_tenantManager = GetRequiredService<ITenantManager>();
_tenantRepository = GetRequiredService<ITenantRepository>();
}
[Fact]
public async Task CreateAsync()
{
var tenant = await _tenantManager.CreateAsync("Test");
tenant.Name.ShouldBe("Test");
}
[Fact]
public async Task Create_Tenant_Name_Can_Not_Duplicate()
{ {
private readonly ITenantManager _tenantManager; await Assert.ThrowsAsync<UserFriendlyException>(async () => await _tenantManager.CreateAsync("volosoft"));
private readonly ITenantRepository _tenantRepository; }
public TenantManager_Tests() [Fact]
{ public async Task ChangeNameAsync()
_tenantManager = GetRequiredService<ITenantManager>(); {
_tenantRepository = GetRequiredService<ITenantRepository>(); var tenant = await _tenantRepository.FindByNameAsync("volosoft");
} tenant.ShouldNotBeNull();
await _tenantManager.ChangeNameAsync(tenant, "newVolosoft");
[Fact]
public async Task CreateAsync() tenant.Name.ShouldBe("newVolosoft");
{ }
var tenant = await _tenantManager.CreateAsync("Test");
tenant.Name.ShouldBe("Test"); [Fact]
} public async Task ChangeName_Tenant_Name_Can_Not_Duplicate()
{
[Fact] var tenant = await _tenantRepository.FindByNameAsync("acme");
public async Task Create_Tenant_Name_Can_Not_Duplicate() tenant.ShouldNotBeNull();
{
await Assert.ThrowsAsync<UserFriendlyException>(async () => await _tenantManager.CreateAsync("volosoft")); await Assert.ThrowsAsync<UserFriendlyException>(async () => await _tenantManager.ChangeNameAsync(tenant, "volosoft"));
}
[Fact]
public async Task ChangeNameAsync()
{
var tenant = await _tenantRepository.FindByNameAsync("volosoft");
tenant.ShouldNotBeNull();
await _tenantManager.ChangeNameAsync(tenant, "newVolosoft");
tenant.Name.ShouldBe("newVolosoft");
}
[Fact]
public async Task ChangeName_Tenant_Name_Can_Not_Duplicate()
{
var tenant = await _tenantRepository.FindByNameAsync("acme");
tenant.ShouldNotBeNull();
await Assert.ThrowsAsync<UserFriendlyException>(async () => await _tenantManager.ChangeNameAsync(tenant, "volosoft"));
}
} }
} }

47
modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantStore_Tests.cs

@ -3,34 +3,33 @@ using Shouldly;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Xunit; using Xunit;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class TenantStore_Tests : AbpTenantManagementDomainTestBase
{ {
public class TenantStore_Tests : AbpTenantManagementDomainTestBase private readonly ITenantStore _tenantStore;
{ private readonly ITenantRepository _tenantRepository;
private readonly ITenantStore _tenantStore;
private readonly ITenantRepository _tenantRepository;
public TenantStore_Tests() public TenantStore_Tests()
{ {
_tenantStore = GetRequiredService<ITenantStore>(); _tenantStore = GetRequiredService<ITenantStore>();
_tenantRepository = GetRequiredService<ITenantRepository>(); _tenantRepository = GetRequiredService<ITenantRepository>();
} }
[Fact] [Fact]
public async Task FindAsyncByName() public async Task FindAsyncByName()
{ {
var acme = await _tenantStore.FindAsync("acme"); var acme = await _tenantStore.FindAsync("acme");
acme.ShouldNotBeNull(); acme.ShouldNotBeNull();
acme.Name.ShouldBe("acme"); acme.Name.ShouldBe("acme");
} }
[Fact] [Fact]
public async Task FindAsyncById() public async Task FindAsyncById()
{ {
var acme = await _tenantRepository.FindByNameAsync("acme"); var acme = await _tenantRepository.FindByNameAsync("acme");
acme.ShouldNotBeNull(); acme.ShouldNotBeNull();
(await _tenantStore.FindAsync(acme.Id)).ShouldNotBeNull(); (await _tenantStore.FindAsync(acme.Id)).ShouldNotBeNull();
}
} }
} }

45
modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/Tenant_Tests.cs

@ -2,34 +2,33 @@
using Shouldly; using Shouldly;
using Xunit; using Xunit;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class Tenant_Tests : AbpTenantManagementDomainTestBase
{ {
public class Tenant_Tests : AbpTenantManagementDomainTestBase private readonly ITenantRepository _tenantRepository;
{
private readonly ITenantRepository _tenantRepository;
public Tenant_Tests() public Tenant_Tests()
{ {
_tenantRepository = GetRequiredService<ITenantRepository>(); _tenantRepository = GetRequiredService<ITenantRepository>();
} }
[Fact] [Fact]
public async Task FindDefaultConnectionString() public async Task FindDefaultConnectionString()
{ {
var acme = await _tenantRepository.FindByNameAsync("acme"); var acme = await _tenantRepository.FindByNameAsync("acme");
acme.ShouldNotBeNull(); acme.ShouldNotBeNull();
acme.FindDefaultConnectionString().ShouldBe("DefaultConnString-Value"); acme.FindDefaultConnectionString().ShouldBe("DefaultConnString-Value");
} }
[Fact] [Fact]
public async Task FindConnectionString() public async Task FindConnectionString()
{ {
var acme = await _tenantRepository.FindByNameAsync("acme"); var acme = await _tenantRepository.FindByNameAsync("acme");
acme.ShouldNotBeNull(); acme.ShouldNotBeNull();
acme.FindConnectionString(Data.ConnectionStrings.DefaultConnectionStringName).ShouldBe("DefaultConnString-Value"); acme.FindConnectionString(Data.ConnectionStrings.DefaultConnectionStringName).ShouldBe("DefaultConnString-Value");
acme.FindConnectionString("MyConnString").ShouldBe("MyConnString-Value"); acme.FindConnectionString("MyConnString").ShouldBe("MyConnString-Value");
}
} }
} }

55
modules/tenant-management/test/Volo.Abp.TenantManagement.EntityFrameworkCore.Tests/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementEntityFrameworkCoreTestModule.cs

@ -8,43 +8,42 @@ using Volo.Abp.EntityFrameworkCore.Sqlite;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.Uow; using Volo.Abp.Uow;
namespace Volo.Abp.TenantManagement.EntityFrameworkCore namespace Volo.Abp.TenantManagement.EntityFrameworkCore;
[DependsOn(
typeof(AbpTenantManagementEntityFrameworkCoreModule),
typeof(AbpTenantManagementTestBaseModule),
typeof(AbpEntityFrameworkCoreSqliteModule)
)]
public class AbpTenantManagementEntityFrameworkCoreTestModule : AbpModule
{ {
[DependsOn( public override void ConfigureServices(ServiceConfigurationContext context)
typeof(AbpTenantManagementEntityFrameworkCoreModule),
typeof(AbpTenantManagementTestBaseModule),
typeof(AbpEntityFrameworkCoreSqliteModule)
)]
public class AbpTenantManagementEntityFrameworkCoreTestModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) var sqliteConnection = CreateDatabaseAndGetConnection();
{
var sqliteConnection = CreateDatabaseAndGetConnection();
Configure<AbpDbContextOptions>(options => Configure<AbpDbContextOptions>(options =>
{
options.Configure(abpDbContextConfigurationContext =>
{ {
options.Configure(abpDbContextConfigurationContext => abpDbContextConfigurationContext.DbContextOptions.UseSqlite(sqliteConnection);
{
abpDbContextConfigurationContext.DbContextOptions.UseSqlite(sqliteConnection);
});
}); });
});
Configure<AbpUnitOfWorkDefaultOptions>(options => Configure<AbpUnitOfWorkDefaultOptions>(options =>
{ {
options.TransactionBehavior = UnitOfWorkTransactionBehavior.Disabled; //EF in-memory database does not support transactions options.TransactionBehavior = UnitOfWorkTransactionBehavior.Disabled; //EF in-memory database does not support transactions
}); });
} }
private static SqliteConnection CreateDatabaseAndGetConnection() private static SqliteConnection CreateDatabaseAndGetConnection()
{ {
var connection = new SqliteConnection("Data Source=:memory:"); var connection = new SqliteConnection("Data Source=:memory:");
connection.Open(); connection.Open();
new TenantManagementDbContext( new TenantManagementDbContext(
new DbContextOptionsBuilder<TenantManagementDbContext>().UseSqlite(connection).Options new DbContextOptionsBuilder<TenantManagementDbContext>().UseSqlite(connection).Options
).GetService<IRelationalDatabaseCreator>().CreateTables(); ).GetService<IRelationalDatabaseCreator>().CreateTables();
return connection; return connection;
}
} }
} }

17
modules/tenant-management/test/Volo.Abp.TenantManagement.EntityFrameworkCore.Tests/Volo/Abp/TenantManagement/EntityFrameworkCore/LazyLoad_Tests.cs

@ -2,19 +2,18 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.TenantManagement.EntityFrameworkCore namespace Volo.Abp.TenantManagement.EntityFrameworkCore;
public class LazyLoad_Tests : LazyLoad_Tests<AbpTenantManagementEntityFrameworkCoreTestModule>
{ {
public class LazyLoad_Tests : LazyLoad_Tests<AbpTenantManagementEntityFrameworkCoreTestModule> protected override void BeforeAddApplication(IServiceCollection services)
{ {
protected override void BeforeAddApplication(IServiceCollection services) services.Configure<AbpDbContextOptions>(options =>
{ {
services.Configure<AbpDbContextOptions>(options => options.PreConfigure<TenantManagementDbContext>(context =>
{ {
options.PreConfigure<TenantManagementDbContext>(context => context.DbContextOptions.UseLazyLoadingProxies();
{
context.DbContextOptions.UseLazyLoadingProxies();
});
}); });
} });
} }
} }

7
modules/tenant-management/test/Volo.Abp.TenantManagement.EntityFrameworkCore.Tests/Volo/Abp/TenantManagement/EntityFrameworkCore/TenantRepository_Tests.cs

@ -1,7 +1,6 @@
namespace Volo.Abp.TenantManagement.EntityFrameworkCore namespace Volo.Abp.TenantManagement.EntityFrameworkCore;
public class TenantRepository_Tests : TenantRepository_Tests<AbpTenantManagementEntityFrameworkCoreTestModule>
{ {
public class TenantRepository_Tests : TenantRepository_Tests<AbpTenantManagementEntityFrameworkCoreTestModule>
{
}
} }

33
modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/AbpTenantManagementMongoDbTestModule.cs

@ -3,25 +3,24 @@ using Volo.Abp.Data;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.Uow; using Volo.Abp.Uow;
namespace Volo.Abp.TenantManagement.MongoDB namespace Volo.Abp.TenantManagement.MongoDB;
[DependsOn(
typeof(AbpTenantManagementMongoDbModule),
typeof(AbpTenantManagementTestBaseModule)
)]
public class AbpTenantManagementMongoDbTestModule : AbpModule
{ {
[DependsOn( public override void ConfigureServices(ServiceConfigurationContext context)
typeof(AbpTenantManagementMongoDbModule),
typeof(AbpTenantManagementTestBaseModule)
)]
public class AbpTenantManagementMongoDbTestModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) var stringArray = MongoDbFixture.ConnectionString.Split('?');
{ var connectionString = stringArray[0].EnsureEndsWith('/') +
var stringArray = MongoDbFixture.ConnectionString.Split('?'); "Db_" +
var connectionString = stringArray[0].EnsureEndsWith('/') + Guid.NewGuid().ToString("N") + "/?" + stringArray[1];
"Db_" +
Guid.NewGuid().ToString("N") + "/?" + stringArray[1];
Configure<AbpDbConnectionOptions>(options => Configure<AbpDbConnectionOptions>(options =>
{ {
options.ConnectionStrings.Default = connectionString; options.ConnectionStrings.Default = connectionString;
}); });
}
} }
} }

27
modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoDbFixture.cs

@ -3,22 +3,21 @@ using Mongo2Go;
using MongoDB.Driver; using MongoDB.Driver;
using Volo.Abp.MongoDB; using Volo.Abp.MongoDB;
namespace Volo.Abp.TenantManagement.MongoDB namespace Volo.Abp.TenantManagement.MongoDB;
public class MongoDbFixture : IDisposable
{ {
public class MongoDbFixture : IDisposable private static readonly MongoDbRunner MongoDbRunner;
{ public static readonly string ConnectionString;
private static readonly MongoDbRunner MongoDbRunner;
public static readonly string ConnectionString;
static MongoDbFixture() static MongoDbFixture()
{ {
MongoDbRunner = MongoDbRunner.Start(singleNodeReplSet: true, singleNodeReplSetWaitTimeout: 20); MongoDbRunner = MongoDbRunner.Start(singleNodeReplSet: true, singleNodeReplSetWaitTimeout: 20);
ConnectionString = MongoDbRunner.ConnectionString; ConnectionString = MongoDbRunner.ConnectionString;
} }
public void Dispose() public void Dispose()
{ {
MongoDbRunner?.Dispose(); MongoDbRunner?.Dispose();
}
} }
} }

13
modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoTestCollection.cs

@ -1,10 +1,9 @@
using Xunit; using Xunit;
namespace Volo.Abp.TenantManagement.MongoDB namespace Volo.Abp.TenantManagement.MongoDB;
[CollectionDefinition(Name)]
public class MongoTestCollection : ICollectionFixture<MongoDbFixture>
{ {
[CollectionDefinition(Name)] public const string Name = "MongoDB Collection";
public class MongoTestCollection : ICollectionFixture<MongoDbFixture> }
{
public const string Name = "MongoDB Collection";
}
}

9
modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/TenantRepository_Tests.cs

@ -1,10 +1,9 @@
using Xunit; using Xunit;
namespace Volo.Abp.TenantManagement.MongoDB namespace Volo.Abp.TenantManagement.MongoDB;
[Collection(MongoTestCollection.Name)]
public class TenantRepository_Tests : TenantRepository_Tests<AbpTenantManagementMongoDbTestModule>
{ {
[Collection(MongoTestCollection.Name)]
public class TenantRepository_Tests : TenantRepository_Tests<AbpTenantManagementMongoDbTestModule>
{
}
} }

35
modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/AbpTenantManagementTestBaseModule.cs

@ -2,28 +2,27 @@
using Volo.Abp.Autofac; using Volo.Abp.Autofac;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
[DependsOn(
typeof(AbpTenantManagementDomainModule),
typeof(AbpAutofacModule),
typeof(AbpTestBaseModule)
)]
public class AbpTenantManagementTestBaseModule : AbpModule
{ {
[DependsOn( public override void OnApplicationInitialization(ApplicationInitializationContext context)
typeof(AbpTenantManagementDomainModule),
typeof(AbpAutofacModule),
typeof(AbpTestBaseModule)
)]
public class AbpTenantManagementTestBaseModule : AbpModule
{ {
public override void OnApplicationInitialization(ApplicationInitializationContext context) SeedTestData(context);
{ }
SeedTestData(context);
}
private static void SeedTestData(ApplicationInitializationContext context) private static void SeedTestData(ApplicationInitializationContext context)
{
using (var scope = context.ServiceProvider.CreateScope())
{ {
using (var scope = context.ServiceProvider.CreateScope()) scope.ServiceProvider
{ .GetRequiredService<AbpTenantManagementTestDataBuilder>()
scope.ServiceProvider .Build();
.GetRequiredService<AbpTenantManagementTestDataBuilder>()
.Build();
}
} }
} }
} }

51
modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/AbpTenantManagementTestDataBuilder.cs

@ -3,35 +3,34 @@ using Volo.Abp.Data;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Threading; using Volo.Abp.Threading;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public class AbpTenantManagementTestDataBuilder : ITransientDependency
{ {
public class AbpTenantManagementTestDataBuilder : ITransientDependency private readonly ITenantRepository _tenantRepository;
{ private readonly ITenantManager _tenantManager;
private readonly ITenantRepository _tenantRepository;
private readonly ITenantManager _tenantManager;
public AbpTenantManagementTestDataBuilder( public AbpTenantManagementTestDataBuilder(
ITenantRepository tenantRepository, ITenantRepository tenantRepository,
ITenantManager tenantManager) ITenantManager tenantManager)
{ {
_tenantRepository = tenantRepository; _tenantRepository = tenantRepository;
_tenantManager = tenantManager; _tenantManager = tenantManager;
} }
public void Build() public void Build()
{ {
AsyncHelper.RunSync(AddTenantsAsync); AsyncHelper.RunSync(AddTenantsAsync);
} }
private async Task AddTenantsAsync() private async Task AddTenantsAsync()
{ {
var acme = await _tenantManager.CreateAsync("acme"); var acme = await _tenantManager.CreateAsync("acme");
acme.ConnectionStrings.Add(new TenantConnectionString(acme.Id, ConnectionStrings.DefaultConnectionStringName, "DefaultConnString-Value")); acme.ConnectionStrings.Add(new TenantConnectionString(acme.Id, ConnectionStrings.DefaultConnectionStringName, "DefaultConnString-Value"));
acme.ConnectionStrings.Add(new TenantConnectionString(acme.Id, "MyConnString", "MyConnString-Value")); acme.ConnectionStrings.Add(new TenantConnectionString(acme.Id, "MyConnString", "MyConnString-Value"));
await _tenantRepository.InsertAsync(acme); await _tenantRepository.InsertAsync(acme);
var volosoft = await _tenantManager.CreateAsync("volosoft"); var volosoft = await _tenantManager.CreateAsync("volosoft");
await _tenantRepository.InsertAsync(volosoft); await _tenantRepository.InsertAsync(volosoft);
}
} }
} }

37
modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/LazyLoad_Tests.cs

@ -5,29 +5,28 @@ using Volo.Abp.Modularity;
using Volo.Abp.Uow; using Volo.Abp.Uow;
using Xunit; using Xunit;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public abstract class LazyLoad_Tests<TStartupModule> : TenantManagementTestBase<TStartupModule>
where TStartupModule : IAbpModule
{ {
public abstract class LazyLoad_Tests<TStartupModule> : TenantManagementTestBase<TStartupModule> public ITenantRepository TenantRepository { get; }
where TStartupModule : IAbpModule
{
public ITenantRepository TenantRepository { get; }
protected LazyLoad_Tests() protected LazyLoad_Tests()
{ {
TenantRepository = GetRequiredService<ITenantRepository>(); TenantRepository = GetRequiredService<ITenantRepository>();
} }
[Fact] [Fact]
public async Task Should_Lazy_Load_Tenant_Collections() public async Task Should_Lazy_Load_Tenant_Collections()
{
using (var uow = GetRequiredService<IUnitOfWorkManager>().Begin())
{ {
using (var uow = GetRequiredService<IUnitOfWorkManager>().Begin()) var role = await TenantRepository.FindByNameAsync("acme", includeDetails: false);
{ role.ConnectionStrings.ShouldNotBeNull();
var role = await TenantRepository.FindByNameAsync("acme", includeDetails: false); role.ConnectionStrings.Any().ShouldBeTrue();
role.ConnectionStrings.ShouldNotBeNull();
role.ConnectionStrings.Any().ShouldBeTrue();
await uow.CompleteAsync(); await uow.CompleteAsync();
}
} }
} }
} }

13
modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/TenantManagementTestBase.cs

@ -1,14 +1,13 @@
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.Testing; using Volo.Abp.Testing;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public abstract class TenantManagementTestBase<TStartupModule> : AbpIntegratedTest<TStartupModule>
where TStartupModule : IAbpModule
{ {
public abstract class TenantManagementTestBase<TStartupModule> : AbpIntegratedTest<TStartupModule> protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
where TStartupModule : IAbpModule
{ {
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) options.UseAutofac();
{
options.UseAutofac();
}
} }
} }

91
modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/TenantRepository_Tests.cs

@ -5,62 +5,61 @@ using Shouldly;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Xunit; using Xunit;
namespace Volo.Abp.TenantManagement namespace Volo.Abp.TenantManagement;
public abstract class TenantRepository_Tests<TStartupModule> : TenantManagementTestBase<TStartupModule>
where TStartupModule : IAbpModule
{ {
public abstract class TenantRepository_Tests<TStartupModule> : TenantManagementTestBase<TStartupModule> public ITenantRepository TenantRepository { get; }
where TStartupModule : IAbpModule
{
public ITenantRepository TenantRepository { get; }
protected TenantRepository_Tests() protected TenantRepository_Tests()
{ {
TenantRepository = GetRequiredService<ITenantRepository>(); TenantRepository = GetRequiredService<ITenantRepository>();
} }
[Fact] [Fact]
public async Task FindByNameAsync() public async Task FindByNameAsync()
{ {
var tenant = await TenantRepository.FindByNameAsync("acme"); var tenant = await TenantRepository.FindByNameAsync("acme");
tenant.ShouldNotBeNull(); tenant.ShouldNotBeNull();
tenant = await TenantRepository.FindByNameAsync("undefined-tenant"); tenant = await TenantRepository.FindByNameAsync("undefined-tenant");
tenant.ShouldBeNull(); tenant.ShouldBeNull();
tenant = await TenantRepository.FindByNameAsync("acme", includeDetails: true); tenant = await TenantRepository.FindByNameAsync("acme", includeDetails: true);
tenant.ShouldNotBeNull(); tenant.ShouldNotBeNull();
tenant.ConnectionStrings.Count.ShouldBeGreaterThanOrEqualTo(2); tenant.ConnectionStrings.Count.ShouldBeGreaterThanOrEqualTo(2);
} }
[Fact] [Fact]
public async Task FindAsync() public async Task FindAsync()
{ {
var tenantId = (await TenantRepository.FindByNameAsync("acme")).Id; var tenantId = (await TenantRepository.FindByNameAsync("acme")).Id;
var tenant = await TenantRepository.FindAsync(tenantId); var tenant = await TenantRepository.FindAsync(tenantId);
tenant.ShouldNotBeNull(); tenant.ShouldNotBeNull();
tenant = await TenantRepository.FindAsync(Guid.NewGuid()); tenant = await TenantRepository.FindAsync(Guid.NewGuid());
tenant.ShouldBeNull(); tenant.ShouldBeNull();
tenant = await TenantRepository.FindAsync(tenantId, includeDetails: true); tenant = await TenantRepository.FindAsync(tenantId, includeDetails: true);
tenant.ShouldNotBeNull(); tenant.ShouldNotBeNull();
tenant.ConnectionStrings.Count.ShouldBeGreaterThanOrEqualTo(2); tenant.ConnectionStrings.Count.ShouldBeGreaterThanOrEqualTo(2);
} }
[Fact] [Fact]
public async Task GetListAsync() public async Task GetListAsync()
{ {
var tenants = await TenantRepository.GetListAsync(); var tenants = await TenantRepository.GetListAsync();
tenants.ShouldContain(t => t.Name == "acme"); tenants.ShouldContain(t => t.Name == "acme");
tenants.ShouldContain(t => t.Name == "volosoft"); tenants.ShouldContain(t => t.Name == "volosoft");
} }
[Fact] [Fact]
public async Task Should_Eager_Load_Tenant_Collections() public async Task Should_Eager_Load_Tenant_Collections()
{ {
var role = await TenantRepository.FindByNameAsync("acme"); var role = await TenantRepository.FindByNameAsync("acme");
role.ConnectionStrings.ShouldNotBeNull(); role.ConnectionStrings.ShouldNotBeNull();
role.ConnectionStrings.Any().ShouldBeTrue(); role.ConnectionStrings.Any().ShouldBeTrue();
}
} }
} }

Loading…
Cancel
Save