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.Threading;
namespace Volo.Abp.TenantManagement
namespace Volo.Abp.TenantManagement;
[DependsOn(
typeof(AbpDddApplicationContractsModule),
typeof(AbpTenantManagementDomainSharedModule),
typeof(AbpAuthorizationAbstractionsModule)
)]
public class AbpTenantManagementApplicationContractsModule : AbpModule
{
[DependsOn(
typeof(AbpDddApplicationContractsModule),
typeof(AbpTenantManagementDomainSharedModule),
typeof(AbpAuthorizationAbstractionsModule)
)]
public class AbpTenantManagementApplicationContractsModule : AbpModule
{
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
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(
TenantManagementModuleExtensionConsts.ModuleName,
TenantManagementModuleExtensionConsts.EntityNames.Tenant,
getApiTypes: new[] { typeof(TenantDto) },
createApiTypes: new[] { typeof(TenantCreateDto) },
updateApiTypes: new[] { typeof(TenantUpdateDto) }
);
});
}
ModuleExtensionConfigurationHelper
.ApplyEntityConfigurationToApi(
TenantManagementModuleExtensionConsts.ModuleName,
TenantManagementModuleExtensionConsts.EntityNames.Tenant,
getApiTypes: new[] { typeof(TenantDto) },
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.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);
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.Delete, L("Permission:Delete"), 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);
}
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.Update, L("Permission:Edit"), 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.ManageConnectionStrings, L("Permission:ManageConnectionStrings"), multiTenancySide: MultiTenancySides.Host);
}
private static LocalizableString L(string name)
{
return LocalizableString.Create<AbpTenantManagementResource>(name);
}
private static LocalizableString L(string 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;
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 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;
namespace Volo.Abp.TenantManagement
namespace Volo.Abp.TenantManagement;
public class TenantCreateDto : TenantCreateOrUpdateDtoBase
{
public class TenantCreateDto : TenantCreateOrUpdateDtoBase
{
[Required]
[EmailAddress]
[MaxLength(256)]
public virtual string AdminEmailAddress { get; set; }
[Required]
[EmailAddress]
[MaxLength(256)]
public virtual string AdminEmailAddress { get; set; }
[Required]
[MaxLength(128)]
public virtual string AdminPassword { get; set; }
}
}
[Required]
[MaxLength(128)]
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.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))]
[Display(Name = "TenantName")]
public string Name { get; set; }
[Required]
[DynamicStringLength(typeof(TenantConsts), nameof(TenantConsts.MaxNameLength))]
[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.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;
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 const string Default = GroupName + ".Tenants";
public const string Create = Default + ".Create";
public const string Update = Default + ".Update";
public const string Delete = Default + ".Delete";
public const string ManageFeatures = Default + ".ManageFeatures";
public const string ManageConnectionStrings = Default + ".ManageConnectionStrings";
}
public static class Tenants
{
public const string Default = GroupName + ".Tenants";
public const string Create = Default + ".Create";
public const string Update = Default + ".Update";
public const string Delete = Default + ".Delete";
public const string ManageFeatures = Default + ".ManageFeatures";
public const string ManageConnectionStrings = Default + ".ManageConnectionStrings";
}
public static string[] GetAll()
{
return ReflectionHelper.GetPublicConstantsRecursively(typeof(TenantManagementPermissions));
}
public static string[] GetAll()
{
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;
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;
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.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))]
[DependsOn(typeof(AbpTenantManagementApplicationContractsModule))]
[DependsOn(typeof(AbpDddApplicationModule))]
public class AbpTenantManagementApplicationModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
public override void ConfigureServices(ServiceConfigurationContext context)
context.Services.AddAutoMapperObjectMapper<AbpTenantManagementApplicationModule>();
Configure<AbpAutoMapperOptions>(options =>
{
context.Services.AddAutoMapperObjectMapper<AbpTenantManagementApplicationModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<AbpTenantManagementApplicationAutoMapperProfile>(validate: true);
});
}
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.ObjectExtending;
namespace Volo.Abp.TenantManagement
namespace Volo.Abp.TenantManagement;
[Authorize(TenantManagementPermissions.Tenants.Default)]
public class TenantAppService : TenantManagementAppServiceBase, ITenantAppService
{
[Authorize(TenantManagementPermissions.Tenants.Default)]
public class TenantAppService : TenantManagementAppServiceBase, ITenantAppService
protected IDataSeeder DataSeeder { get; }
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; }
protected ITenantRepository TenantRepository { get; }
protected ITenantManager TenantManager { get; }
protected IDistributedEventBus DistributedEventBus { get; }
public TenantAppService(
ITenantRepository tenantRepository,
ITenantManager tenantManager,
IDataSeeder dataSeeder,
IDistributedEventBus distributedEventBus)
{
DataSeeder = dataSeeder;
TenantRepository = tenantRepository;
TenantManager = tenantManager;
DistributedEventBus = distributedEventBus;
}
DataSeeder = dataSeeder;
TenantRepository = tenantRepository;
TenantManager = tenantManager;
DistributedEventBus = distributedEventBus;
}
public virtual async Task<TenantDto> GetAsync(Guid id)
{
return ObjectMapper.Map<Tenant, TenantDto>(
await TenantRepository.GetAsync(id)
);
}
public virtual async Task<TenantDto> GetAsync(Guid id)
{
return ObjectMapper.Map<Tenant, TenantDto>(
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);
}
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)
);
input.Sorting = nameof(Tenant.Name);
}
[Authorize(TenantManagementPermissions.Tenants.Create)]
public virtual async Task<TenantDto> CreateAsync(TenantCreateDto input)
{
var tenant = await TenantManager.CreateAsync(input.Name);
input.MapExtraPropertiesTo(tenant);
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)
);
}
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(
new TenantCreatedEto
await CurrentUnitOfWork.SaveChangesAsync();
await DistributedEventBus.PublishAsync(
new TenantCreatedEto
{
Id = tenant.Id,
Name = tenant.Name,
Properties =
{
Id = tenant.Id,
Name = tenant.Name,
Properties =
{
{ "AdminEmail", input.AdminEmailAddress },
{ "AdminPassword", input.AdminPassword }
}
});
}
});
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)
using (CurrentTenant.Change(tenant.Id, tenant.Name))
{
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);
input.MapExtraPropertiesTo(tenant);
[Authorize(TenantManagementPermissions.Tenants.Update)]
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)]
public virtual async Task DeleteAsync(Guid id)
{
var tenant = await TenantRepository.FindAsync(id);
if (tenant == null)
{
return;
}
await TenantRepository.UpdateAsync(tenant);
await TenantRepository.DeleteAsync(tenant);
}
return ObjectMapper.Map<Tenant, TenantDto>(tenant);
}
[Authorize(TenantManagementPermissions.Tenants.ManageConnectionStrings)]
public virtual async Task<string> GetDefaultConnectionStringAsync(Guid id)
[Authorize(TenantManagementPermissions.Tenants.Delete)]
public virtual async Task DeleteAsync(Guid id)
{
var tenant = await TenantRepository.FindAsync(id);
if (tenant == null)
{
var tenant = await TenantRepository.GetAsync(id);
return tenant?.FindDefaultConnectionString();
return;
}
[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);
}
await TenantRepository.DeleteAsync(tenant);
}
[Authorize(TenantManagementPermissions.Tenants.ManageConnectionStrings)]
public virtual async Task DeleteDefaultConnectionStringAsync(Guid id)
{
var tenant = await TenantRepository.GetAsync(id);
tenant.RemoveDefaultConnectionString();
await TenantRepository.UpdateAsync(tenant);
}
[Authorize(TenantManagementPermissions.Tenants.ManageConnectionStrings)]
public virtual async Task<string> GetDefaultConnectionStringAsync(Guid id)
{
var tenant = await TenantRepository.GetAsync(id);
return tenant?.FindDefaultConnectionString();
}
[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.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.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.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;
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.UI.Navigation;
namespace Volo.Abp.TenantManagement.Blazor
namespace Volo.Abp.TenantManagement.Blazor;
[DependsOn(
typeof(AbpAutoMapperModule),
typeof(AbpTenantManagementApplicationContractsModule),
typeof(AbpFeatureManagementBlazorModule)
)]
public class AbpTenantManagementBlazorModule : AbpModule
{
[DependsOn(
typeof(AbpAutoMapperModule),
typeof(AbpTenantManagementApplicationContractsModule),
typeof(AbpFeatureManagementBlazorModule)
)]
public class AbpTenantManagementBlazorModule : AbpModule
private static readonly OneTimeRunner OneTimeRunner = new();
public override void ConfigureServices(ServiceConfigurationContext context)
{
private static readonly OneTimeRunner OneTimeRunner = new();
public override void ConfigureServices(ServiceConfigurationContext context)
context.Services.AddAutoMapperObjectMapper<AbpTenantManagementBlazorModule>();
Configure<AbpAutoMapperOptions>(options =>
{
context.Services.AddAutoMapperObjectMapper<AbpTenantManagementBlazorModule>();
options.AddProfile<AbpTenantManagementBlazorAutoMapperProfile>(validate: true);
});
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<AbpTenantManagementBlazorAutoMapperProfile>(validate: true);
});
Configure<AbpNavigationOptions>(options =>
{
options.MenuContributors.Add(new TenantManagementBlazorMenuContributor());
});
Configure<AbpNavigationOptions>(options =>
{
options.MenuContributors.Add(new TenantManagementBlazorMenuContributor());
});
Configure<AbpRouterOptions>(options =>
{
options.AdditionalAssemblies.Add(typeof(AbpTenantManagementBlazorModule).Assembly);
});
}
Configure<AbpRouterOptions>(options =>
{
options.AdditionalAssemblies.Add(typeof(AbpTenantManagementBlazorModule).Assembly);
});
}
public override void PostConfigureServices(ServiceConfigurationContext context)
public override void PostConfigureServices(ServiceConfigurationContext context)
{
OneTimeRunner.Run(() =>
{
OneTimeRunner.Run(() =>
{
ModuleExtensionConfigurationHelper
.ApplyEntityConfigurationToUi(
TenantManagementModuleExtensionConsts.ModuleName,
TenantManagementModuleExtensionConsts.EntityNames.Tenant,
createFormTypes: new[] { typeof(TenantCreateDto) },
editFormTypes: new[] { typeof(TenantUpdateDto) }
);
});
}
ModuleExtensionConfigurationHelper
.ApplyEntityConfigurationToUi(
TenantManagementModuleExtensionConsts.ModuleName,
TenantManagementModuleExtensionConsts.EntityNames.Tenant,
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.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(
TenantManagementMenuNames.GroupName,
l["Menu:TenantManagement"],
icon: "fa fa-users"
);
administrationMenu.AddItem(tenantManagementMenuItem);
var tenantManagementMenuItem = new ApplicationMenuItem(
TenantManagementMenuNames.GroupName,
l["Menu:TenantManagement"],
icon: "fa fa-users"
);
administrationMenu.AddItem(tenantManagementMenuItem);
tenantManagementMenuItem.AddItem(new ApplicationMenuItem(
TenantManagementMenuNames.Tenants,
l["Tenants"],
url: "~/tenant-management/tenants"
).RequirePermissions(TenantManagementPermissions.Tenants.Default));
tenantManagementMenuItem.AddItem(new ApplicationMenuItem(
TenantManagementMenuNames.Tenants,
l["Tenants"],
url: "~/tenant-management/tenants"
).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.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 string ManageFeaturesPolicyName;
protected bool HasManageFeaturesPermission;
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()
{
LocalizationResource = typeof(AbpTenantManagementResource);
ObjectMapperContext = typeof(AbpTenantManagementBlazorModule);
public TenantManagement()
{
LocalizationResource = typeof(AbpTenantManagementResource);
ObjectMapperContext = typeof(AbpTenantManagementBlazorModule);
CreatePolicyName = TenantManagementPermissions.Tenants.Create;
UpdatePolicyName = TenantManagementPermissions.Tenants.Update;
DeletePolicyName = TenantManagementPermissions.Tenants.Delete;
CreatePolicyName = TenantManagementPermissions.Tenants.Create;
UpdatePolicyName = TenantManagementPermissions.Tenants.Update;
DeletePolicyName = TenantManagementPermissions.Tenants.Delete;
ManageFeaturesPolicyName = TenantManagementPermissions.Tenants.ManageFeatures;
}
ManageFeaturesPolicyName = TenantManagementPermissions.Tenants.ManageFeatures;
}
protected override async Task SetPermissionsAsync()
{
await base.SetPermissionsAsync();
protected override async Task SetPermissionsAsync()
{
await base.SetPermissionsAsync();
HasManageFeaturesPermission = await AuthorizationService.IsGrantedAsync(ManageFeaturesPolicyName);
}
HasManageFeaturesPermission = await AuthorizationService.IsGrantedAsync(ManageFeaturesPolicyName);
}
protected override string GetDeleteConfirmationMessage(TenantDto entity)
{
return string.Format(L["TenantDeletionConfirmationMessage"], entity.Name);
}
protected override string GetDeleteConfirmationMessage(TenantDto entity)
{
return string.Format(L["TenantDeletionConfirmationMessage"], entity.Name);
}
protected override ValueTask SetToolbarItemsAsync()
{
Toolbar.AddButton(L["NewTenant"],
OpenCreateModalAsync,
IconName.Add,
requiredPolicyName: CreatePolicyName);
protected override ValueTask SetToolbarItemsAsync()
{
Toolbar.AddButton(L["NewTenant"],
OpenCreateModalAsync,
IconName.Add,
requiredPolicyName: CreatePolicyName);
return base.SetToolbarItemsAsync();
}
return base.SetToolbarItemsAsync();
}
protected override ValueTask SetEntityActionsAsync()
{
EntityActions
.Get<TenantManagement>()
.AddRange(new EntityAction[]
{
protected override ValueTask SetEntityActionsAsync()
{
EntityActions
.Get<TenantManagement>()
.AddRange(new EntityAction[]
{
new EntityAction
{
Text = L["Edit"],
@ -90,16 +90,16 @@ namespace Volo.Abp.TenantManagement.Blazor.Pages.TenantManagement
Clicked = async (data) => await DeleteEntityAsync(data.As<TenantDto>()),
ConfirmationMessage = (data) => GetDeleteConfirmationMessage(data.As<TenantDto>())
}
});
});
return base.SetEntityActionsAsync();
}
return base.SetEntityActionsAsync();
}
protected override ValueTask SetTableColumnsAsync()
{
TenantManagementTableColumns
.AddRange(new TableColumn[]
{
protected override ValueTask SetTableColumnsAsync()
{
TenantManagementTableColumns
.AddRange(new TableColumn[]
{
new TableColumn
{
Title = L["Actions"],
@ -110,13 +110,12 @@ namespace Volo.Abp.TenantManagement.Blazor.Pages.TenantManagement
Title = L["TenantName"],
Data = nameof(TenantDto.Name),
},
});
});
TenantManagementTableColumns.AddRange(GetExtensionTableColumns(
TenantManagementModuleExtensionConsts.ModuleName,
TenantManagementModuleExtensionConsts.EntityNames.Tenant));
TenantManagementTableColumns.AddRange(GetExtensionTableColumns(
TenantManagementModuleExtensionConsts.ModuleName,
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 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(
Action<EntityExtensionConfiguration> configureAction)
{
return this.ConfigureEntity(
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 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(
this ModuleExtensionConfigurationDictionary modules,
Action<TenantManagementModuleExtensionConfiguration> configureAction)
{
return modules.ConfigureModule(
TenantManagementModuleExtensionConsts.ModuleName,
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 const string Tenant = "Tenant";
}
public static class EntityNames
{
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.VirtualFileSystem;
namespace Volo.Abp.TenantManagement
namespace Volo.Abp.TenantManagement;
[DependsOn(typeof(AbpValidationModule))]
public class AbpTenantManagementDomainSharedModule : AbpModule
{
[DependsOn(typeof(AbpValidationModule))]
public class AbpTenantManagementDomainSharedModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
public override void ConfigureServices(ServiceConfigurationContext context)
Configure<AbpVirtualFileSystemOptions>(options =>
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpTenantManagementDomainSharedModule>();
});
options.FileSets.AddEmbedded<AbpTenantManagementDomainSharedModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<AbpTenantManagementResource>("en")
.AddBaseTypes(
typeof(AbpValidationResource)
).AddVirtualJson("/Volo/Abp/TenantManagement/Localization/Resources");
});
}
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<AbpTenantManagementResource>("en")
.AddBaseTypes(
typeof(AbpValidationResource)
).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;
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>
public static int MaxNameLength { get; set; } = 64;
/// <summary>
/// Default value: 64
/// </summary>
public static int MaxNameLength { get; set; } = 64;
/// <summary>
/// Default value: 1024
/// </summary>
public static int MaxValueLength { get; set; } = 1024;
}
}
/// <summary>
/// Default value: 1024
/// </summary>
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>
public static int MaxNameLength { get; set; } = 64;
}
/// <summary>
/// Default value: 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;
namespace Volo.Abp.TenantManagement
namespace Volo.Abp.TenantManagement;
[Serializable]
public class TenantEto
{
[Serializable]
public class TenantEto
{
public Guid Id { get; set; }
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;
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.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)
{
connStrings[connectionString.Name] = connectionString.Value;
}
foreach (var connectionString in tenant.ConnectionStrings)
{
connStrings[connectionString.Name] = connectionString.Value;
}
return connStrings;
});
})
.ForMember(x => x.IsActive, x => x.Ignore());
return connStrings;
});
})
.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.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))]
[DependsOn(typeof(AbpTenantManagementDomainSharedModule))]
[DependsOn(typeof(AbpDataModule))]
[DependsOn(typeof(AbpDddDomainModule))]
[DependsOn(typeof(AbpAutoMapperModule))]
[DependsOn(typeof(AbpCachingModule))]
public class AbpTenantManagementDomainModule : AbpModule
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
public override void ConfigureServices(ServiceConfigurationContext context)
{
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
context.Services.AddAutoMapperObjectMapper<AbpTenantManagementDomainModule>();
public override void ConfigureServices(ServiceConfigurationContext context)
Configure<AbpAutoMapperOptions>(options =>
{
context.Services.AddAutoMapperObjectMapper<AbpTenantManagementDomainModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<AbpTenantManagementDomainMappingProfile>(validate: true);
});
options.AddProfile<AbpTenantManagementDomainMappingProfile>(validate: true);
});
Configure<AbpDistributedEntityEventOptions>(options =>
{
options.EtoMappings.Add<Tenant, TenantEto>();
});
}
Configure<AbpDistributedEntityEventOptions>(options =>
{
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,
TenantManagementModuleExtensionConsts.EntityNames.Tenant,
typeof(Tenant)
);
});
}
ModuleExtensionConfigurationHelper.ApplyEntityConfigurationToEntity(
TenantManagementModuleExtensionConsts.ModuleName,
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 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 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,
bool includeDetails = true,
CancellationToken cancellationToken = default);
Task<Tenant> FindByNameAsync(
string name,
bool includeDetails = true,
CancellationToken cancellationToken = default);
[Obsolete("Use FindByNameAsync method.")]
Tenant FindByName(
string name,
bool includeDetails = true
);
[Obsolete("Use FindByNameAsync method.")]
Tenant FindByName(
string name,
bool includeDetails = true
);
[Obsolete("Use FindAsync method.")]
Tenant FindById(
Guid id,
bool includeDetails = true
);
[Obsolete("Use FindAsync method.")]
Tenant FindById(
Guid id,
bool includeDetails = true
);
Task<List<Tenant>> GetListAsync(
string sorting = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
string filter = null,
bool includeDetails = false,
CancellationToken cancellationToken = default);
Task<List<Tenant>> GetListAsync(
string sorting = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
string filter = null,
bool includeDetails = false,
CancellationToken cancellationToken = default);
Task<long> GetCountAsync(
string filter = null,
CancellationToken cancellationToken = default);
}
Task<long> GetCountAsync(
string filter = null,
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 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)
: base(id)
{
SetName(name);
protected internal Tenant(Guid id, [NotNull] string name)
: base(id)
{
SetName(name);
ConnectionStrings = new List<TenantConnectionString>();
}
ConnectionStrings = new List<TenantConnectionString>();
}
[CanBeNull]
public virtual string FindDefaultConnectionString()
{
return FindConnectionString(Data.ConnectionStrings.DefaultConnectionStringName);
}
[CanBeNull]
public virtual string FindDefaultConnectionString()
{
return FindConnectionString(Data.ConnectionStrings.DefaultConnectionStringName);
}
[CanBeNull]
public virtual string FindConnectionString(string name)
{
return ConnectionStrings.FirstOrDefault(c => c.Name == name)?.Value;
}
[CanBeNull]
public virtual string FindConnectionString(string name)
{
return ConnectionStrings.FirstOrDefault(c => c.Name == name)?.Value;
}
public virtual void SetDefaultConnectionString(string connectionString)
{
SetConnectionString(Data.ConnectionStrings.DefaultConnectionStringName, connectionString);
}
public virtual void SetDefaultConnectionString(string 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);
if (tenantConnectionString != null)
{
tenantConnectionString.SetValue(connectionString);
}
else
{
ConnectionStrings.Add(new TenantConnectionString(Id, name, connectionString));
}
tenantConnectionString.SetValue(connectionString);
}
public virtual void RemoveDefaultConnectionString()
else
{
RemoveConnectionString(Data.ConnectionStrings.DefaultConnectionStringName);
ConnectionStrings.Add(new TenantConnectionString(Id, name, connectionString));
}
}
public virtual void RemoveConnectionString(string name)
{
var tenantConnectionString = ConnectionStrings.FirstOrDefault(x => x.Name == name);
public virtual void RemoveDefaultConnectionString()
{
RemoveConnectionString(Data.ConnectionStrings.DefaultConnectionStringName);
}
if (tenantConnectionString != null)
{
ConnectionStrings.Remove(tenantConnectionString);
}
}
public virtual void RemoveConnectionString(string name)
{
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 Volo.Abp.MultiTenancy;
namespace Volo.Abp.TenantManagement
namespace Volo.Abp.TenantManagement;
[Serializable]
[IgnoreMultiTenancy]
public class TenantCacheItem
{
[Serializable]
[IgnoreMultiTenancy]
public class TenantCacheItem
{
private const string CacheKeyFormat = "i:{0},n:{1}";
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)
{
Value = value;
}
public TenantCacheItem(TenantConfiguration 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.");
}
return string.Format(CacheKeyFormat,
id?.ToString() ?? "null",
(name.IsNullOrWhiteSpace() ? "null" : name));
throw new AbpException("Both id and name can't be invalid.");
}
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.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)
{
Cache = cache;
}
public TenantCacheItemInvalidator(IDistributedCache<TenantCacheItem> cache)
{
Cache = cache;
}
public virtual async Task HandleEventAsync(EntityChangedEventData<Tenant> eventData)
{
await Cache.RemoveAsync(TenantCacheItem.CalculateCacheKey(eventData.Entity.Id, null), considerUow: true);
await Cache.RemoveAsync(TenantCacheItem.CalculateCacheKey(null, eventData.Entity.Name), considerUow: true);
}
public virtual async Task HandleEventAsync(EntityChangedEventData<Tenant> eventData)
{
await Cache.RemoveAsync(TenantCacheItem.CalculateCacheKey(eventData.Entity.Id, null), 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 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)
{
TenantId = tenantId;
Name = Check.NotNullOrWhiteSpace(name, nameof(name), TenantConnectionStringConsts.MaxNameLength);
SetValue(value);
}
public TenantConnectionString(Guid tenantId, [NotNull] string name, [NotNull] string value)
{
TenantId = tenantId;
Name = Check.NotNullOrWhiteSpace(name, nameof(name), TenantConnectionStringConsts.MaxNameLength);
SetValue(value);
}
public virtual void SetValue([NotNull] string value)
{
Value = Check.NotNullOrWhiteSpace(value, nameof(value), TenantConnectionStringConsts.MaxValueLength);
}
public virtual void SetValue([NotNull] string value)
{
Value = Check.NotNullOrWhiteSpace(value, nameof(value), TenantConnectionStringConsts.MaxValueLength);
}
public override object[] GetKeys()
{
return new object[] { TenantId, Name };
}
public override object[] GetKeys()
{
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 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)
{
TenantRepository = tenantRepository;
public TenantManager(ITenantRepository tenantRepository)
{
TenantRepository = tenantRepository;
}
}
public virtual async Task<Tenant> CreateAsync(string name)
{
Check.NotNull(name, nameof(name));
public virtual async Task<Tenant> CreateAsync(string name)
{
Check.NotNull(name, nameof(name));
await ValidateNameAsync(name);
return new Tenant(GuidGenerator.Create(), name);
}
await ValidateNameAsync(name);
return new Tenant(GuidGenerator.Create(), name);
}
public virtual async Task ChangeNameAsync(Tenant tenant, string name)
{
Check.NotNull(tenant, nameof(tenant));
Check.NotNull(name, nameof(name));
public virtual async Task ChangeNameAsync(Tenant tenant, string name)
{
Check.NotNull(tenant, nameof(tenant));
Check.NotNull(name, nameof(name));
await ValidateNameAsync(name, tenant.Id);
tenant.SetName(name);
}
await ValidateNameAsync(name, tenant.Id);
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);
if (tenant != null && tenant.Id != expectedId)
{
throw new UserFriendlyException("Duplicate tenancy name: " + name); //TODO: A domain exception would be better..?
}
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.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; }
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)
{
TenantRepository = tenantRepository;
ObjectMapper = objectMapper;
CurrentTenant = currentTenant;
Cache = cache;
}
TenantRepository = tenantRepository;
ObjectMapper = objectMapper;
CurrentTenant = currentTenant;
Cache = cache;
}
public virtual async Task<TenantConfiguration> FindAsync(string name)
{
return (await GetCacheItemAsync(null, name)).Value;
}
public virtual async Task<TenantConfiguration> FindAsync(string name)
{
return (await GetCacheItemAsync(null, name)).Value;
}
public virtual async Task<TenantConfiguration> FindAsync(Guid id)
{
return (await GetCacheItemAsync(id, null)).Value;
}
public virtual async Task<TenantConfiguration> FindAsync(Guid id)
{
return (await GetCacheItemAsync(id, null)).Value;
}
[Obsolete("Use FindAsync method.")]
public virtual TenantConfiguration Find(string name)
{
return (GetCacheItem(null, name)).Value;
}
[Obsolete("Use FindAsync method.")]
public virtual TenantConfiguration Find(string name)
{
return (GetCacheItem(null, name)).Value;
}
[Obsolete("Use FindAsync method.")]
public virtual TenantConfiguration Find(Guid id)
[Obsolete("Use FindAsync method.")]
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);
var cacheItem = await Cache.GetAsync(cacheKey, considerUow: true);
if (cacheItem != null)
using (CurrentTenant.Change(null)) //TODO: No need this if we can implement to define host side (or tenant-independent) entities!
{
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.FindAsync(id.Value);
return await SetCacheAsync(cacheKey, tenant);
}
var tenant = await TenantRepository.FindByNameAsync(name);
return await SetCacheAsync(cacheKey, tenant);
}
}
if (!name.IsNullOrWhiteSpace())
{
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.");
}
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;
}
[Obsolete("Use GetCacheItemAsync method.")]
protected virtual TenantCacheItem GetCacheItem(Guid? id, string name)
if (id.HasValue)
{
var cacheKey = CalculateCacheKey(id, name);
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!
{
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.")]
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;
}
throw new AbpException("Both id and name can't be invalid.");
}
protected virtual string CalculateCacheKey(Guid? id, string name)
{
return TenantCacheItem.CalculateCacheKey(id, name);
}
[Obsolete("Use SetCacheAsync method.")]
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)
{
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 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(
this ModelBuilder builder)
{
Check.NotNull(builder, nameof(builder));
Check.NotNull(builder, nameof(builder));
if (builder.IsTenantOnlyDatabase())
{
return;
}
if (builder.IsTenantOnlyDatabase())
{
return;
}
builder.Entity<Tenant>(b =>
{
b.ToTable(AbpTenantManagementDbProperties.DbTablePrefix + "Tenants", AbpTenantManagementDbProperties.DbSchema);
builder.Entity<Tenant>(b =>
{
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 =>
{
b.ToTable(AbpTenantManagementDbProperties.DbTablePrefix + "TenantConnectionStrings", AbpTenantManagementDbProperties.DbSchema);
builder.Entity<TenantConnectionString>(b =>
{
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.Value).IsRequired().HasMaxLength(TenantConnectionStringConsts.MaxValueLength);
b.Property(cs => cs.Name).IsRequired().HasMaxLength(TenantConnectionStringConsts.MaxNameLength);
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.Modularity;
namespace Volo.Abp.TenantManagement.EntityFrameworkCore
namespace Volo.Abp.TenantManagement.EntityFrameworkCore;
[DependsOn(typeof(AbpTenantManagementDomainModule))]
[DependsOn(typeof(AbpEntityFrameworkCoreModule))]
public class AbpTenantManagementEntityFrameworkCoreModule : AbpModule
{
[DependsOn(typeof(AbpTenantManagementDomainModule))]
[DependsOn(typeof(AbpEntityFrameworkCoreModule))]
public class AbpTenantManagementEntityFrameworkCoreModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
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.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(
string name,
bool includeDetails = true,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.IncludeDetails(includeDetails)
.OrderBy(t => t.Id)
.FirstOrDefaultAsync(t => t.Name == name, GetCancellationToken(cancellationToken));
}
public virtual async Task<Tenant> FindByNameAsync(
string name,
bool includeDetails = true,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.IncludeDetails(includeDetails)
.OrderBy(t => t.Id)
.FirstOrDefaultAsync(t => t.Name == name, GetCancellationToken(cancellationToken));
}
[Obsolete("Use FindByNameAsync method.")]
public virtual Tenant FindByName(string name, bool includeDetails = true)
{
return DbSet
.IncludeDetails(includeDetails)
.OrderBy(t => t.Id)
.FirstOrDefault(t => t.Name == name);
}
[Obsolete("Use FindByNameAsync method.")]
public virtual Tenant FindByName(string name, bool includeDetails = true)
{
return DbSet
.IncludeDetails(includeDetails)
.OrderBy(t => t.Id)
.FirstOrDefault(t => t.Name == name);
}
[Obsolete("Use FindAsync method.")]
public virtual Tenant FindById(Guid id, bool includeDetails = true)
{
return DbSet
.IncludeDetails(includeDetails)
.OrderBy(t => t.Id)
.FirstOrDefault(t => t.Id == id);
}
[Obsolete("Use FindAsync method.")]
public virtual Tenant FindById(Guid id, bool includeDetails = true)
{
return DbSet
.IncludeDetails(includeDetails)
.OrderBy(t => t.Id)
.FirstOrDefault(t => t.Id == id);
}
public virtual async Task<List<Tenant>> GetListAsync(
string sorting = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
string filter = null,
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.IncludeDetails(includeDetails)
.WhereIf(
!filter.IsNullOrWhiteSpace(),
u =>
u.Name.Contains(filter)
)
.OrderBy(sorting.IsNullOrEmpty() ? nameof(Tenant.Name) : sorting)
.PageBy(skipCount, maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Tenant>> GetListAsync(
string sorting = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
string filter = null,
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.IncludeDetails(includeDetails)
.WhereIf(
!filter.IsNullOrWhiteSpace(),
u =>
u.Name.Contains(filter)
)
.OrderBy(sorting.IsNullOrEmpty() ? nameof(Tenant.Name) : sorting)
.PageBy(skipCount, maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<long> GetCountAsync(string filter = null, CancellationToken cancellationToken = default)
{
return await (await GetQueryableAsync())
.WhereIf(
!filter.IsNullOrWhiteSpace(),
u =>
u.Name.Contains(filter)
).CountAsync(cancellationToken: cancellationToken);
}
public virtual async Task<long> GetCountAsync(string filter = null, CancellationToken cancellationToken = default)
{
return await (await GetQueryableAsync())
.WhereIf(
!filter.IsNullOrWhiteSpace(),
u =>
u.Name.Contains(filter)
).CountAsync(cancellationToken: cancellationToken);
}
[Obsolete("Use WithDetailsAsync method.")]
public override IQueryable<Tenant> WithDetails()
{
return GetQueryable().IncludeDetails();
}
[Obsolete("Use WithDetailsAsync method.")]
public override IQueryable<Tenant> WithDetails()
{
return GetQueryable().IncludeDetails();
}
public override async Task<IQueryable<Tenant>> WithDetailsAsync()
{
return (await GetQueryableAsync()).IncludeDetails();
}
public override async Task<IQueryable<Tenant>> WithDetailsAsync()
{
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.MultiTenancy;
namespace Volo.Abp.TenantManagement.EntityFrameworkCore
namespace Volo.Abp.TenantManagement.EntityFrameworkCore;
[IgnoreMultiTenancy]
[ConnectionStringName(AbpTenantManagementDbProperties.ConnectionStringName)]
public interface ITenantManagementDbContext : IEfCoreDbContext
{
[IgnoreMultiTenancy]
[ConnectionStringName(AbpTenantManagementDbProperties.ConnectionStringName)]
public interface ITenantManagementDbContext : IEfCoreDbContext
{
DbSet<Tenant> Tenants { get; }
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.MultiTenancy;
namespace Volo.Abp.TenantManagement.EntityFrameworkCore
namespace Volo.Abp.TenantManagement.EntityFrameworkCore;
[IgnoreMultiTenancy]
[ConnectionStringName(AbpTenantManagementDbProperties.ConnectionStringName)]
public class TenantManagementDbContext : AbpDbContext<TenantManagementDbContext>, ITenantManagementDbContext
{
[IgnoreMultiTenancy]
[ConnectionStringName(AbpTenantManagementDbProperties.ConnectionStringName)]
public class TenantManagementDbContext : AbpDbContext<TenantManagementDbContext>, ITenantManagementDbContext
{
public DbSet<Tenant> Tenants { get; set; }
public DbSet<Tenant> Tenants { get; set; }
public DbSet<TenantConnectionString> TenantConnectionStrings { get; set; }
public DbSet<TenantConnectionString> TenantConnectionStrings { get; set; }
public TenantManagementDbContext(DbContextOptions<TenantManagementDbContext> options)
: base(options)
{
}
public TenantManagementDbContext(DbContextOptions<TenantManagementDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
protected override void OnModelCreating(ModelBuilder 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 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
.Include(x => x.ConnectionStrings);
return queryable;
}
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
// 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.VirtualFileSystem;
namespace Volo.Abp.TenantManagement
namespace Volo.Abp.TenantManagement;
[DependsOn(
typeof(AbpTenantManagementApplicationContractsModule),
typeof(AbpHttpClientModule))]
public class AbpTenantManagementHttpApiClientModule : AbpModule
{
[DependsOn(
typeof(AbpTenantManagementApplicationContractsModule),
typeof(AbpHttpClientModule))]
public class AbpTenantManagementHttpApiClientModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddStaticHttpClientProxies(
typeof(AbpTenantManagementApplicationContractsModule).Assembly,
TenantManagementRemoteServiceConsts.RemoteServiceName
);
context.Services.AddStaticHttpClientProxies(
typeof(AbpTenantManagementApplicationContractsModule).Assembly,
TenantManagementRemoteServiceConsts.RemoteServiceName
);
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpTenantManagementHttpApiClientModule>();
});
}
Configure<AbpVirtualFileSystemOptions>(options =>
{
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 Microsoft.Extensions.DependencyInjection;
namespace Volo.Abp.TenantManagement
namespace Volo.Abp.TenantManagement;
[DependsOn(
typeof(AbpTenantManagementApplicationContractsModule),
typeof(AbpFeatureManagementHttpApiModule),
typeof(AbpAspNetCoreMvcModule)
)]
public class AbpTenantManagementHttpApiModule : AbpModule
{
[DependsOn(
typeof(AbpTenantManagementApplicationContractsModule),
typeof(AbpFeatureManagementHttpApiModule),
typeof(AbpAspNetCoreMvcModule)
)]
public class AbpTenantManagementHttpApiModule : AbpModule
public override void PreConfigureServices(ServiceConfigurationContext context)
{
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>()
.AddBaseTypes(
typeof(AbpFeatureManagementResource),
typeof(AbpUiResource));
});
}
options.Resources
.Get<AbpTenantManagementResource>()
.AddBaseTypes(
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.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]
[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; }
protected ITenantAppService TenantAppService { get; }
public TenantController(ITenantAppService tenantAppService)
{
TenantAppService = tenantAppService;
}
public TenantController(ITenantAppService tenantAppService)
{
TenantAppService = tenantAppService;
}
[HttpGet]
[Route("{id}")]
public virtual Task<TenantDto> GetAsync(Guid id)
{
return TenantAppService.GetAsync(id);
}
[HttpGet]
[Route("{id}")]
public virtual Task<TenantDto> GetAsync(Guid id)
{
return TenantAppService.GetAsync(id);
}
[HttpGet]
public virtual Task<PagedResultDto<TenantDto>> GetListAsync(GetTenantsInput input)
{
return TenantAppService.GetListAsync(input);
}
[HttpGet]
public virtual Task<PagedResultDto<TenantDto>> GetListAsync(GetTenantsInput input)
{
return TenantAppService.GetListAsync(input);
}
[HttpPost]
public virtual Task<TenantDto> CreateAsync(TenantCreateDto input)
{
ValidateModel();
return TenantAppService.CreateAsync(input);
}
[HttpPost]
public virtual Task<TenantDto> CreateAsync(TenantCreateDto input)
{
ValidateModel();
return TenantAppService.CreateAsync(input);
}
[HttpPut]
[Route("{id}")]
public virtual Task<TenantDto> UpdateAsync(Guid id, TenantUpdateDto input)
{
return TenantAppService.UpdateAsync(id, input);
}
[HttpPut]
[Route("{id}")]
public virtual Task<TenantDto> UpdateAsync(Guid id, TenantUpdateDto input)
{
return TenantAppService.UpdateAsync(id, input);
}
[HttpDelete]
[Route("{id}")]
public virtual Task DeleteAsync(Guid id)
{
return TenantAppService.DeleteAsync(id);
}
[HttpDelete]
[Route("{id}")]
public virtual Task DeleteAsync(Guid id)
{
return TenantAppService.DeleteAsync(id);
}
[HttpGet]
[Route("{id}/default-connection-string")]
public virtual Task<string> GetDefaultConnectionStringAsync(Guid id)
{
return TenantAppService.GetDefaultConnectionStringAsync(id);
}
[HttpGet]
[Route("{id}/default-connection-string")]
public virtual Task<string> GetDefaultConnectionStringAsync(Guid id)
{
return TenantAppService.GetDefaultConnectionStringAsync(id);
}
[HttpPut]
[Route("{id}/default-connection-string")]
public virtual Task UpdateDefaultConnectionStringAsync(Guid id, string defaultConnectionString)
{
return TenantAppService.UpdateDefaultConnectionStringAsync(id, defaultConnectionString);
}
[HttpPut]
[Route("{id}/default-connection-string")]
public virtual Task UpdateDefaultConnectionStringAsync(Guid id, string defaultConnectionString)
{
return TenantAppService.UpdateDefaultConnectionStringAsync(id, defaultConnectionString);
}
[HttpDelete]
[Route("{id}/default-connection-string")]
public virtual Task DeleteDefaultConnectionStringAsync(Guid id)
{
return TenantAppService.DeleteDefaultConnectionStringAsync(id);
}
[HttpDelete]
[Route("{id}/default-connection-string")]
public virtual Task DeleteDefaultConnectionStringAsync(Guid 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.VirtualFileSystem;
namespace Volo.Abp.TenantManagement
namespace Volo.Abp.TenantManagement;
[DependsOn(
typeof(AbpStudioModuleInstallerModule),
typeof(AbpVirtualFileSystemModule)
)]
public class AbpTenantManagementInstallerModule : AbpModule
{
[DependsOn(
typeof(AbpStudioModuleInstallerModule),
typeof(AbpVirtualFileSystemModule)
)]
public class AbpTenantManagementInstallerModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
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.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)]
[ExposeServices(typeof(IModuleInstallingPipelineBuilder))]
public class AuditLoggingInstallerPipelineBuilder : ModuleInstallingPipelineBuilderBase, IModuleInstallingPipelineBuilder, ITransientDependency
public async Task<ModuleInstallingPipeline> BuildAsync(ModuleInstallingContext context)
{
public async Task<ModuleInstallingPipeline> BuildAsync(ModuleInstallingContext context)
{
context.AddEfCoreConfigurationMethodDeclaration(
new EfCoreConfigurationMethodDeclaration(
"Volo.Abp.TenantManagement.EntityFrameworkCore",
"ConfigureTenantManagement"
)
);
return GetBasePipeline(context);
}
context.AddEfCoreConfigurationMethodDeclaration(
new EfCoreConfigurationMethodDeclaration(
"Volo.Abp.TenantManagement.EntityFrameworkCore",
"ConfigureTenantManagement"
)
);
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;
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(
this IMongoModelBuilder builder)
{
Check.NotNull(builder, nameof(builder));
Check.NotNull(builder, nameof(builder));
builder.Entity<Tenant>(b =>
{
b.CollectionName = AbpTenantManagementDbProperties.DbTablePrefix + "Tenants";
});
}
builder.Entity<Tenant>(b =>
{
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.MongoDB;
namespace Volo.Abp.TenantManagement.MongoDB
namespace Volo.Abp.TenantManagement.MongoDB;
[DependsOn(
typeof(AbpTenantManagementDomainModule),
typeof(AbpMongoDbModule)
)]
public class AbpTenantManagementMongoDbModule : AbpModule
{
[DependsOn(
typeof(AbpTenantManagementDomainModule),
typeof(AbpMongoDbModule)
)]
public class AbpTenantManagementMongoDbModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
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.MultiTenancy;
namespace Volo.Abp.TenantManagement.MongoDB
namespace Volo.Abp.TenantManagement.MongoDB;
[IgnoreMultiTenancy]
[ConnectionStringName(AbpTenantManagementDbProperties.ConnectionStringName)]
public interface ITenantManagementMongoDbContext : IAbpMongoDbContext
{
[IgnoreMultiTenancy]
[ConnectionStringName(AbpTenantManagementDbProperties.ConnectionStringName)]
public interface ITenantManagementMongoDbContext : IAbpMongoDbContext
{
IMongoCollection<Tenant> Tenants { get; }
}
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.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(
string name,
bool includeDetails = true,
CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync(cancellationToken))
.FirstOrDefaultAsync(t => t.Name == name, GetCancellationToken(cancellationToken));
}
public virtual async Task<Tenant> FindByNameAsync(
string name,
bool includeDetails = true,
CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync(cancellationToken))
.FirstOrDefaultAsync(t => t.Name == name, GetCancellationToken(cancellationToken));
}
[Obsolete("Use FindByNameAsync method.")]
public virtual Tenant FindByName(string name, bool includeDetails = true)
{
return GetMongoQueryable()
.FirstOrDefault(t => t.Name == name);
}
[Obsolete("Use FindByNameAsync method.")]
public virtual Tenant FindByName(string name, bool includeDetails = true)
{
return GetMongoQueryable()
.FirstOrDefault(t => t.Name == name);
}
[Obsolete("Use FindAsync method.")]
public virtual Tenant FindById(Guid id, bool includeDetails = true)
{
return GetMongoQueryable()
.FirstOrDefault(t => t.Id == id);
}
[Obsolete("Use FindAsync method.")]
public virtual Tenant FindById(Guid id, bool includeDetails = true)
{
return GetMongoQueryable()
.FirstOrDefault(t => t.Id == id);
}
public virtual async Task<List<Tenant>> GetListAsync(
string sorting = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
string filter = null,
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync(cancellationToken))
.WhereIf<Tenant, IMongoQueryable<Tenant>>(
!filter.IsNullOrWhiteSpace(),
u =>
u.Name.Contains(filter)
)
.OrderBy(sorting.IsNullOrEmpty() ? nameof(Tenant.Name) : sorting)
.As<IMongoQueryable<Tenant>>()
.PageBy<Tenant, IMongoQueryable<Tenant>>(skipCount, maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Tenant>> GetListAsync(
string sorting = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
string filter = null,
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync(cancellationToken))
.WhereIf<Tenant, IMongoQueryable<Tenant>>(
!filter.IsNullOrWhiteSpace(),
u =>
u.Name.Contains(filter)
)
.OrderBy(sorting.IsNullOrEmpty() ? nameof(Tenant.Name) : sorting)
.As<IMongoQueryable<Tenant>>()
.PageBy<Tenant, IMongoQueryable<Tenant>>(skipCount, maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<long> GetCountAsync(string filter = null, CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync(cancellationToken))
.WhereIf<Tenant, IMongoQueryable<Tenant>>(
!filter.IsNullOrWhiteSpace(),
u =>
u.Name.Contains(filter)
).CountAsync(cancellationToken: cancellationToken);
}
public virtual async Task<long> GetCountAsync(string filter = null, CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync(cancellationToken))
.WhereIf<Tenant, IMongoQueryable<Tenant>>(
!filter.IsNullOrWhiteSpace(),
u =>
u.Name.Contains(filter)
).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.MultiTenancy;
namespace Volo.Abp.TenantManagement.MongoDB
namespace Volo.Abp.TenantManagement.MongoDB;
[IgnoreMultiTenancy]
[ConnectionStringName(AbpTenantManagementDbProperties.ConnectionStringName)]
public class TenantManagementMongoDbContext : AbpMongoDbContext, ITenantManagementMongoDbContext
{
[IgnoreMultiTenancy]
[ConnectionStringName(AbpTenantManagementDbProperties.ConnectionStringName)]
public class TenantManagementMongoDbContext : AbpMongoDbContext, ITenantManagementMongoDbContext
{
public IMongoCollection<Tenant> Tenants => Collection<Tenant>();
public IMongoCollection<Tenant> Tenants => Collection<Tenant>();
protected override void CreateModel(IMongoModelBuilder modelBuilder)
{
base.CreateModel(modelBuilder);
protected override void CreateModel(IMongoModelBuilder 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.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
CreateMap<CreateModalModel.TenantInfoModel, TenantCreateDto>()
.MapExtraProperties();
//CreateModal
CreateMap<CreateModalModel.TenantInfoModel, TenantCreateDto>()
.MapExtraProperties();
//EditModal
CreateMap<EditModalModel.TenantInfoModel, TenantUpdateDto>()
.MapExtraProperties();
}
//EditModal
CreateMap<EditModalModel.TenantInfoModel, TenantUpdateDto>()
.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.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))]
[DependsOn(typeof(AbpAspNetCoreMvcUiBootstrapModule))]
[DependsOn(typeof(AbpFeatureManagementWebModule))]
[DependsOn(typeof(AbpAutoMapperModule))]
public class AbpTenantManagementWebModule : AbpModule
{
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
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 =>
{
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpTenantManagementWebModule).Assembly);
});
}
PreConfigure<IMvcBuilder>(mvcBuilder =>
{
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 =>
{
options.FileSets.AddEmbedded<AbpTenantManagementWebModule>();
});
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpTenantManagementWebModule>();
});
context.Services.AddAutoMapperObjectMapper<AbpTenantManagementWebModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<AbpTenantManagementWebAutoMapperProfile>(validate: true);
});
context.Services.AddAutoMapperObjectMapper<AbpTenantManagementWebModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<AbpTenantManagementWebAutoMapperProfile>(validate: true);
});
Configure<RazorPagesOptions>(options =>
{
options.Conventions.AuthorizePage("/TenantManagement/Tenants/Index", TenantManagementPermissions.Tenants.Default);
options.Conventions.AuthorizePage("/TenantManagement/Tenants/CreateModal", TenantManagementPermissions.Tenants.Create);
options.Conventions.AuthorizePage("/TenantManagement/Tenants/EditModal", TenantManagementPermissions.Tenants.Update);
});
Configure<RazorPagesOptions>(options =>
{
options.Conventions.AuthorizePage("/TenantManagement/Tenants/Index", TenantManagementPermissions.Tenants.Default);
options.Conventions.AuthorizePage("/TenantManagement/Tenants/CreateModal", TenantManagementPermissions.Tenants.Create);
options.Conventions.AuthorizePage("/TenantManagement/Tenants/EditModal", TenantManagementPermissions.Tenants.Update);
});
Configure<AbpPageToolbarOptions>(options =>
{
options.Configure<Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants.IndexModel>(
toolbar =>
{
toolbar.AddButton(
LocalizableString.Create<AbpTenantManagementResource>("ManageHostFeatures"),
icon: "cog",
name: "ManageHostFeatures",
requiredPolicyName: FeatureManagementPermissions.ManageHostFeatures
);
Configure<AbpPageToolbarOptions>(options =>
{
options.Configure<Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants.IndexModel>(
toolbar =>
{
toolbar.AddButton(
LocalizableString.Create<AbpTenantManagementResource>("ManageHostFeatures"),
icon: "cog",
name: "ManageHostFeatures",
requiredPolicyName: FeatureManagementPermissions.ManageHostFeatures
);
toolbar.AddButton(
LocalizableString.Create<AbpTenantManagementResource>("NewTenant"),
icon: "plus",
name: "CreateTenant",
requiredPolicyName: TenantManagementPermissions.Tenants.Create
);
}
);
});
toolbar.AddButton(
LocalizableString.Create<AbpTenantManagementResource>("NewTenant"),
icon: "plus",
name: "CreateTenant",
requiredPolicyName: TenantManagementPermissions.Tenants.Create
);
}
);
});
Configure<DynamicJavaScriptProxyOptions>(options =>
{
options.DisableModule(TenantManagementRemoteServiceConsts.ModuleName);
});
}
Configure<DynamicJavaScriptProxyOptions>(options =>
{
options.DisableModule(TenantManagementRemoteServiceConsts.ModuleName);
});
}
public override void PostConfigureServices(ServiceConfigurationContext context)
public override void PostConfigureServices(ServiceConfigurationContext context)
{
OneTimeRunner.Run(() =>
{
OneTimeRunner.Run(() =>
{
ModuleExtensionConfigurationHelper
.ApplyEntityConfigurationToUi(
TenantManagementModuleExtensionConsts.ModuleName,
TenantManagementModuleExtensionConsts.EntityNames.Tenant,
createFormTypes: new[] { typeof(Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants.CreateModalModel.TenantInfoModel) },
editFormTypes: new[] { typeof(Volo.Abp.TenantManagement.Web.Pages.TenantManagement.Tenants.EditModalModel.TenantInfoModel) }
);
});
}
ModuleExtensionConfigurationHelper
.ApplyEntityConfigurationToUi(
TenantManagementModuleExtensionConsts.ModuleName,
TenantManagementModuleExtensionConsts.EntityNames.Tenant,
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.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");
administrationMenu.AddItem(tenantManagementMenuItem);
var tenantManagementMenuItem = new ApplicationMenuItem(TenantManagementMenuNames.GroupName, l["Menu:TenantManagement"], icon: "fa fa-users");
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.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]
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
{
[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; }
}
[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.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)
{
TenantAppService = tenantAppService;
}
public EditModalModel(ITenantAppService tenantAppService)
{
TenantAppService = tenantAppService;
}
public virtual async Task<IActionResult> OnGetAsync(Guid id)
{
Tenant = ObjectMapper.Map<TenantDto, TenantInfoModel>(
await TenantAppService.GetAsync(id)
);
public virtual async Task<IActionResult> OnGetAsync(Guid id)
{
Tenant = ObjectMapper.Map<TenantDto, TenantInfoModel>(
await TenantAppService.GetAsync(id)
);
return Page();
}
return Page();
}
public virtual async Task<IActionResult> OnPostAsync()
{
ValidateModel();
public virtual async Task<IActionResult> OnPostAsync()
{
ValidateModel();
var input = ObjectMapper.Map<TenantInfoModel, TenantUpdateDto>(Tenant);
await TenantAppService.UpdateAsync(Tenant.Id, input);
var input = ObjectMapper.Map<TenantInfoModel, TenantUpdateDto>(Tenant);
await TenantAppService.UpdateAsync(Tenant.Id, input);
return NoContent();
}
return NoContent();
}
public class TenantInfoModel : ExtensibleObject, IHasConcurrencyStamp
{
[HiddenInput]
public Guid Id { get; set; }
public class TenantInfoModel : ExtensibleObject, IHasConcurrencyStamp
{
[HiddenInput]
public Guid Id { get; set; }
[Required]
[DynamicStringLength(typeof(TenantConsts), nameof(TenantConsts.MaxNameLength))]
[Display(Name = "DisplayName:TenantName")]
public string Name { get; set; }
[Required]
[DynamicStringLength(typeof(TenantConsts), nameof(TenantConsts.MaxNameLength))]
[Display(Name = "DisplayName:TenantName")]
public string Name { get; set; }
[HiddenInput]
public string ConcurrencyStamp { get; set; }
}
[HiddenInput]
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.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()
{
return Task.FromResult<IActionResult>(Page());
}
public virtual Task<IActionResult> OnPostAsync()
{
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;
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 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.TenantManagement.EntityFrameworkCore;
namespace Volo.Abp.TenantManagement
namespace Volo.Abp.TenantManagement;
[DependsOn(
typeof(AbpTenantManagementApplicationModule),
typeof(AbpTenantManagementEntityFrameworkCoreTestModule))]
public class AbpTenantManagementApplicationTestModule : AbpModule
{
[DependsOn(
typeof(AbpTenantManagementApplicationModule),
typeof(AbpTenantManagementEntityFrameworkCoreTestModule))]
public class AbpTenantManagementApplicationTestModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
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 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()
{
_tenantAppService = GetRequiredService<ITenantAppService>();
}
[Fact]
public async Task GetAsync()
{
var tenantInDb = UsingDbContext(dbContext => dbContext.Tenants.First());
var tenant = await _tenantAppService.GetAsync(tenantInDb.Id);
tenant.Name.ShouldBe(tenantInDb.Name);
}
[Fact]
public async Task GetAsync()
{
var tenantInDb = UsingDbContext(dbContext => dbContext.Tenants.First());
var tenant = await _tenantAppService.GetAsync(tenantInDb.Id);
tenant.Name.ShouldBe(tenantInDb.Name);
}
[Fact]
public async Task GetListAsync()
{
var result = await _tenantAppService.GetListAsync(new GetTenantsInput());
result.TotalCount.ShouldBeGreaterThan(0);
result.Items.ShouldContain(t => t.Name == "acme");
result.Items.ShouldContain(t => t.Name == "volosoft");
}
[Fact]
public async Task GetListAsync()
{
var result = await _tenantAppService.GetListAsync(new GetTenantsInput());
result.TotalCount.ShouldBeGreaterThan(0);
result.Items.ShouldContain(t => t.Name == "acme");
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();
[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");
}
tenants.ShouldContain(t => t.Name == "acme");
tenants.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.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]
public async Task CreateAsync()
{
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);
tenant.Id.ShouldNotBe(default(Guid));
}
[Fact]
public async Task CreateAsync_Should_Not_Allow_Duplicate_Names()
{
await Assert.ThrowsAsync<UserFriendlyException>(async () =>
{
await _tenantAppService.CreateAsync(new TenantCreateDto { Name = "acme", AdminEmailAddress = "admin@admin.com", AdminPassword = "123456" });
});
}
[Fact]
public async Task UpdateAsync()
tenants.FindIndex(t => t.Name == "acme").ShouldBeGreaterThan(tenants.FindIndex(t => t.Name == "volosoft"));
}
[Fact]
public async Task CreateAsync()
{
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);
tenant.Id.ShouldNotBe(default(Guid));
}
[Fact]
public async Task CreateAsync_Should_Not_Allow_Duplicate_Names()
{
await Assert.ThrowsAsync<UserFriendlyException>(async () =>
{
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" });
result.Id.ShouldBe(acme.Id);
result.Name.ShouldBe("acme-renamed");
[Fact]
public async Task UpdateAsync()
{
var acme = UsingDbContext(dbContext => dbContext.Tenants.Single(t => t.Name == "acme"));
var acmeUpdated = UsingDbContext(dbContext => dbContext.Tenants.Single(t => t.Id == acme.Id));
acmeUpdated.Name.ShouldBe("acme-renamed");
}
var result = await _tenantAppService.UpdateAsync(acme.Id, new TenantUpdateDto { Name = "acme-renamed" });
result.Id.ShouldBe(acme.Id);
result.Name.ShouldBe("acme-renamed");
[Fact]
public async Task UpdateAsync_Should_Not_Allow_Duplicate_Names()
{
var acme = UsingDbContext(dbContext => dbContext.Tenants.Single(t => t.Name == "acme"));
var acmeUpdated = UsingDbContext(dbContext => dbContext.Tenants.Single(t => t.Id == acme.Id));
acmeUpdated.Name.ShouldBe("acme-renamed");
}
await Assert.ThrowsAsync<UserFriendlyException>(async () =>
{
await _tenantAppService.UpdateAsync(acme.Id, new TenantUpdateDto { Name = "volosoft" });
});
}
[Fact]
public async Task UpdateAsync_Should_Not_Allow_Duplicate_Names()
{
var acme = UsingDbContext(dbContext => dbContext.Tenants.Single(t => t.Name == "acme"));
[Fact]
public async Task DeleteAsync()
await Assert.ThrowsAsync<UserFriendlyException>(async () =>
{
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 =>
{
dbContext.Tenants.Any(t => t.Id == acme.Id).ShouldBeFalse();
});
}
UsingDbContext(dbContext =>
{
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.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.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 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]
public void Test()
using (CultureHelper.Use("en-gb"))
{
using (CultureHelper.Use("en"))
{
_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?");
}
_stringLocalizer["TenantDeletionConfirmationMessage"].Value
.ShouldBe("Tenant '{0}' will be deleted. Is that OK?");
}
using (CultureHelper.Use("tr"))
{
_stringLocalizer["TenantDeletionConfirmationMessage"].Value
.ShouldBe("'{0}' isimli müşteri silinecektir. Onaylıyor musunuz?");
}
using (CultureHelper.Use("tr"))
{
_stringLocalizer["TenantDeletionConfirmationMessage"].Value
.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 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 ITenantRepository _tenantRepository;
private readonly IDistributedCache<TenantCacheItem> _cache;
private readonly ITenantStore _tenantStore;
private readonly ITenantRepository _tenantRepository;
public TenantCacheItemInvalidator_Tests()
{
_cache = GetRequiredService<IDistributedCache<TenantCacheItem>>();
_tenantStore = GetRequiredService<ITenantStore>();
_tenantRepository = GetRequiredService<ITenantRepository>();
}
public TenantCacheItemInvalidator_Tests()
{
_cache = GetRequiredService<IDistributedCache<TenantCacheItem>>();
_tenantStore = GetRequiredService<ITenantStore>();
_tenantRepository = GetRequiredService<ITenantRepository>();
}
[Fact]
public async Task Get_Tenant_Should_Cached()
{
var acme = await _tenantRepository.FindByNameAsync("acme");
acme.ShouldNotBeNull();
[Fact]
public async Task Get_Tenant_Should_Cached()
{
var acme = await _tenantRepository.FindByNameAsync("acme");
acme.ShouldNotBeNull();
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(acme.Id, null))).ShouldBeNull();
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(null, acme.Name))).ShouldBeNull();
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(acme.Id, null))).ShouldBeNull();
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(null, acme.Name))).ShouldBeNull();
await _tenantStore.FindAsync(acme.Id);
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(acme.Id, null))).ShouldNotBeNull();
await _tenantStore.FindAsync(acme.Id);
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(acme.Id, null))).ShouldNotBeNull();
await _tenantStore.FindAsync(acme.Name);
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(null, acme.Name))).ShouldNotBeNull();
await _tenantStore.FindAsync(acme.Name);
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(null, acme.Name))).ShouldNotBeNull();
var volosoft = _tenantRepository.FindByName("volosoft");
volosoft.ShouldNotBeNull();
var volosoft = _tenantRepository.FindByName("volosoft");
volosoft.ShouldNotBeNull();
(_cache.Get(TenantCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldBeNull();
(_cache.Get(TenantCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldBeNull();
(_cache.Get(TenantCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldBeNull();
(_cache.Get(TenantCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldBeNull();
_tenantStore.Find(volosoft.Id);
(_cache.Get(TenantCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldNotBeNull();
_tenantStore.Find(volosoft.Id);
(_cache.Get(TenantCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldNotBeNull();
_tenantStore.Find(volosoft.Name);
(_cache.Get(TenantCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldNotBeNull();
}
_tenantStore.Find(volosoft.Name);
(_cache.Get(TenantCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldNotBeNull();
}
[Fact]
public async Task Cache_Should_Invalidator_When_Tenant_Changed()
{
var acme = await _tenantRepository.FindByNameAsync("acme");
acme.ShouldNotBeNull();
[Fact]
public async Task Cache_Should_Invalidator_When_Tenant_Changed()
{
var acme = await _tenantRepository.FindByNameAsync("acme");
acme.ShouldNotBeNull();
// FindAsync will cache tenant.
await _tenantStore.FindAsync(acme.Id);
await _tenantStore.FindAsync(acme.Name);
// FindAsync will cache tenant.
await _tenantStore.FindAsync(acme.Id);
await _tenantStore.FindAsync(acme.Name);
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(acme.Id, null))).ShouldNotBeNull();
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(null, acme.Name))).ShouldNotBeNull();
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(acme.Id, null))).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(null, acme.Name))).ShouldBeNull();
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(acme.Id, null))).ShouldBeNull();
(await _cache.GetAsync(TenantCacheItem.CalculateCacheKey(null, acme.Name))).ShouldBeNull();
var volosoft = await _tenantRepository.FindByNameAsync("volosoft");
volosoft.ShouldNotBeNull();
var volosoft = await _tenantRepository.FindByNameAsync("volosoft");
volosoft.ShouldNotBeNull();
// Find will cache tenant.
_tenantStore.Find(volosoft.Id);
_tenantStore.Find(volosoft.Name);
// Find will cache tenant.
_tenantStore.Find(volosoft.Id);
_tenantStore.Find(volosoft.Name);
(_cache.Get(TenantCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldNotBeNull();
(_cache.Get(TenantCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldNotBeNull();
(_cache.Get(TenantCacheItem.CalculateCacheKey(volosoft.Id, null))).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(null, volosoft.Name))).ShouldBeNull();
}
(_cache.Get(TenantCacheItem.CalculateCacheKey(volosoft.Id, null))).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 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]
[InlineData("aaa")]
[InlineData("bbb")]
public void SetValue(string value)
{
var tenantConnectionString =
new TenantConnectionString(Guid.NewGuid(), "MyConnString", "MyConnString-Value");
tenantConnectionString.SetValue(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 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;
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()
{
await Assert.ThrowsAsync<UserFriendlyException>(async () => await _tenantManager.CreateAsync("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"));
}
await Assert.ThrowsAsync<UserFriendlyException>(async () => await _tenantManager.CreateAsync("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 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()
{
_tenantStore = GetRequiredService<ITenantStore>();
_tenantRepository = GetRequiredService<ITenantRepository>();
}
public TenantStore_Tests()
{
_tenantStore = GetRequiredService<ITenantStore>();
_tenantRepository = GetRequiredService<ITenantRepository>();
}
[Fact]
public async Task FindAsyncByName()
{
var acme = await _tenantStore.FindAsync("acme");
acme.ShouldNotBeNull();
acme.Name.ShouldBe("acme");
}
[Fact]
public async Task FindAsyncByName()
{
var acme = await _tenantStore.FindAsync("acme");
acme.ShouldNotBeNull();
acme.Name.ShouldBe("acme");
}
[Fact]
public async Task FindAsyncById()
{
var acme = await _tenantRepository.FindByNameAsync("acme");
acme.ShouldNotBeNull();
[Fact]
public async Task FindAsyncById()
{
var acme = await _tenantRepository.FindByNameAsync("acme");
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 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()
{
_tenantRepository = GetRequiredService<ITenantRepository>();
}
public Tenant_Tests()
{
_tenantRepository = GetRequiredService<ITenantRepository>();
}
[Fact]
public async Task FindDefaultConnectionString()
{
var acme = await _tenantRepository.FindByNameAsync("acme");
[Fact]
public async Task FindDefaultConnectionString()
{
var acme = await _tenantRepository.FindByNameAsync("acme");
acme.ShouldNotBeNull();
acme.FindDefaultConnectionString().ShouldBe("DefaultConnString-Value");
}
acme.ShouldNotBeNull();
acme.FindDefaultConnectionString().ShouldBe("DefaultConnString-Value");
}
[Fact]
public async Task FindConnectionString()
{
var acme = await _tenantRepository.FindByNameAsync("acme");
[Fact]
public async Task FindConnectionString()
{
var acme = await _tenantRepository.FindByNameAsync("acme");
acme.ShouldNotBeNull();
acme.FindConnectionString(Data.ConnectionStrings.DefaultConnectionStringName).ShouldBe("DefaultConnString-Value");
acme.FindConnectionString("MyConnString").ShouldBe("MyConnString-Value");
}
acme.ShouldNotBeNull();
acme.FindConnectionString(Data.ConnectionStrings.DefaultConnectionStringName).ShouldBe("DefaultConnString-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.Uow;
namespace Volo.Abp.TenantManagement.EntityFrameworkCore
namespace Volo.Abp.TenantManagement.EntityFrameworkCore;
[DependsOn(
typeof(AbpTenantManagementEntityFrameworkCoreModule),
typeof(AbpTenantManagementTestBaseModule),
typeof(AbpEntityFrameworkCoreSqliteModule)
)]
public class AbpTenantManagementEntityFrameworkCoreTestModule : AbpModule
{
[DependsOn(
typeof(AbpTenantManagementEntityFrameworkCoreModule),
typeof(AbpTenantManagementTestBaseModule),
typeof(AbpEntityFrameworkCoreSqliteModule)
)]
public class AbpTenantManagementEntityFrameworkCoreTestModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
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 =>
{
options.TransactionBehavior = UnitOfWorkTransactionBehavior.Disabled; //EF in-memory database does not support transactions
Configure<AbpUnitOfWorkDefaultOptions>(options =>
{
options.TransactionBehavior = UnitOfWorkTransactionBehavior.Disabled; //EF in-memory database does not support transactions
});
}
}
private static SqliteConnection CreateDatabaseAndGetConnection()
{
var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();
private static SqliteConnection CreateDatabaseAndGetConnection()
{
var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();
new TenantManagementDbContext(
new DbContextOptionsBuilder<TenantManagementDbContext>().UseSqlite(connection).Options
).GetService<IRelationalDatabaseCreator>().CreateTables();
new TenantManagementDbContext(
new DbContextOptionsBuilder<TenantManagementDbContext>().UseSqlite(connection).Options
).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 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.Uow;
namespace Volo.Abp.TenantManagement.MongoDB
namespace Volo.Abp.TenantManagement.MongoDB;
[DependsOn(
typeof(AbpTenantManagementMongoDbModule),
typeof(AbpTenantManagementTestBaseModule)
)]
public class AbpTenantManagementMongoDbTestModule : AbpModule
{
[DependsOn(
typeof(AbpTenantManagementMongoDbModule),
typeof(AbpTenantManagementTestBaseModule)
)]
public class AbpTenantManagementMongoDbTestModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var stringArray = MongoDbFixture.ConnectionString.Split('?');
var connectionString = stringArray[0].EnsureEndsWith('/') +
"Db_" +
Guid.NewGuid().ToString("N") + "/?" + stringArray[1];
var stringArray = MongoDbFixture.ConnectionString.Split('?');
var connectionString = stringArray[0].EnsureEndsWith('/') +
"Db_" +
Guid.NewGuid().ToString("N") + "/?" + stringArray[1];
Configure<AbpDbConnectionOptions>(options =>
{
options.ConnectionStrings.Default = connectionString;
});
}
Configure<AbpDbConnectionOptions>(options =>
{
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 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()
{
MongoDbRunner = MongoDbRunner.Start(singleNodeReplSet: true, singleNodeReplSetWaitTimeout: 20);
ConnectionString = MongoDbRunner.ConnectionString;
}
static MongoDbFixture()
{
MongoDbRunner = MongoDbRunner.Start(singleNodeReplSet: true, singleNodeReplSetWaitTimeout: 20);
ConnectionString = MongoDbRunner.ConnectionString;
}
public void Dispose()
{
MongoDbRunner?.Dispose();
}
public void 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;
namespace Volo.Abp.TenantManagement.MongoDB
namespace Volo.Abp.TenantManagement.MongoDB;
[CollectionDefinition(Name)]
public class MongoTestCollection : ICollectionFixture<MongoDbFixture>
{
[CollectionDefinition(Name)]
public class MongoTestCollection : ICollectionFixture<MongoDbFixture>
{
public const string Name = "MongoDB Collection";
}
}
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;
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.Modularity;
namespace Volo.Abp.TenantManagement
namespace Volo.Abp.TenantManagement;
[DependsOn(
typeof(AbpTenantManagementDomainModule),
typeof(AbpAutofacModule),
typeof(AbpTestBaseModule)
)]
public class AbpTenantManagementTestBaseModule : AbpModule
{
[DependsOn(
typeof(AbpTenantManagementDomainModule),
typeof(AbpAutofacModule),
typeof(AbpTestBaseModule)
)]
public class AbpTenantManagementTestBaseModule : AbpModule
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
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>()
.Build();
}
scope.ServiceProvider
.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.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(
ITenantRepository tenantRepository,
ITenantManager tenantManager)
{
_tenantRepository = tenantRepository;
_tenantManager = tenantManager;
}
public AbpTenantManagementTestDataBuilder(
ITenantRepository tenantRepository,
ITenantManager tenantManager)
{
_tenantRepository = tenantRepository;
_tenantManager = tenantManager;
}
public void Build()
{
AsyncHelper.RunSync(AddTenantsAsync);
}
public void Build()
{
AsyncHelper.RunSync(AddTenantsAsync);
}
private async Task AddTenantsAsync()
{
var acme = await _tenantManager.CreateAsync("acme");
acme.ConnectionStrings.Add(new TenantConnectionString(acme.Id, ConnectionStrings.DefaultConnectionStringName, "DefaultConnString-Value"));
acme.ConnectionStrings.Add(new TenantConnectionString(acme.Id, "MyConnString", "MyConnString-Value"));
await _tenantRepository.InsertAsync(acme);
private async Task AddTenantsAsync()
{
var acme = await _tenantManager.CreateAsync("acme");
acme.ConnectionStrings.Add(new TenantConnectionString(acme.Id, ConnectionStrings.DefaultConnectionStringName, "DefaultConnString-Value"));
acme.ConnectionStrings.Add(new TenantConnectionString(acme.Id, "MyConnString", "MyConnString-Value"));
await _tenantRepository.InsertAsync(acme);
var volosoft = await _tenantManager.CreateAsync("volosoft");
await _tenantRepository.InsertAsync(volosoft);
}
var volosoft = await _tenantManager.CreateAsync("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 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>
where TStartupModule : IAbpModule
{
public ITenantRepository TenantRepository { get; }
public ITenantRepository TenantRepository { get; }
protected LazyLoad_Tests()
{
TenantRepository = GetRequiredService<ITenantRepository>();
}
protected LazyLoad_Tests()
{
TenantRepository = GetRequiredService<ITenantRepository>();
}
[Fact]
public async Task Should_Lazy_Load_Tenant_Collections()
[Fact]
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();
role.ConnectionStrings.Any().ShouldBeTrue();
var role = await TenantRepository.FindByNameAsync("acme", includeDetails: false);
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.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>
where TStartupModule : IAbpModule
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
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 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>
where TStartupModule : IAbpModule
{
public ITenantRepository TenantRepository { get; }
public ITenantRepository TenantRepository { get; }
protected TenantRepository_Tests()
{
TenantRepository = GetRequiredService<ITenantRepository>();
}
protected TenantRepository_Tests()
{
TenantRepository = GetRequiredService<ITenantRepository>();
}
[Fact]
public async Task FindByNameAsync()
{
var tenant = await TenantRepository.FindByNameAsync("acme");
tenant.ShouldNotBeNull();
[Fact]
public async Task FindByNameAsync()
{
var tenant = await TenantRepository.FindByNameAsync("acme");
tenant.ShouldNotBeNull();
tenant = await TenantRepository.FindByNameAsync("undefined-tenant");
tenant.ShouldBeNull();
tenant = await TenantRepository.FindByNameAsync("undefined-tenant");
tenant.ShouldBeNull();
tenant = await TenantRepository.FindByNameAsync("acme", includeDetails: true);
tenant.ShouldNotBeNull();
tenant.ConnectionStrings.Count.ShouldBeGreaterThanOrEqualTo(2);
}
tenant = await TenantRepository.FindByNameAsync("acme", includeDetails: true);
tenant.ShouldNotBeNull();
tenant.ConnectionStrings.Count.ShouldBeGreaterThanOrEqualTo(2);
}
[Fact]
public async Task FindAsync()
{
var tenantId = (await TenantRepository.FindByNameAsync("acme")).Id;
[Fact]
public async Task FindAsync()
{
var tenantId = (await TenantRepository.FindByNameAsync("acme")).Id;
var tenant = await TenantRepository.FindAsync(tenantId);
tenant.ShouldNotBeNull();
var tenant = await TenantRepository.FindAsync(tenantId);
tenant.ShouldNotBeNull();
tenant = await TenantRepository.FindAsync(Guid.NewGuid());
tenant.ShouldBeNull();
tenant = await TenantRepository.FindAsync(Guid.NewGuid());
tenant.ShouldBeNull();
tenant = await TenantRepository.FindAsync(tenantId, includeDetails: true);
tenant.ShouldNotBeNull();
tenant.ConnectionStrings.Count.ShouldBeGreaterThanOrEqualTo(2);
}
tenant = await TenantRepository.FindAsync(tenantId, includeDetails: true);
tenant.ShouldNotBeNull();
tenant.ConnectionStrings.Count.ShouldBeGreaterThanOrEqualTo(2);
}
[Fact]
public async Task GetListAsync()
{
var tenants = await TenantRepository.GetListAsync();
tenants.ShouldContain(t => t.Name == "acme");
tenants.ShouldContain(t => t.Name == "volosoft");
}
[Fact]
public async Task GetListAsync()
{
var tenants = await TenantRepository.GetListAsync();
tenants.ShouldContain(t => t.Name == "acme");
tenants.ShouldContain(t => t.Name == "volosoft");
}
[Fact]
public async Task Should_Eager_Load_Tenant_Collections()
{
var role = await TenantRepository.FindByNameAsync("acme");
role.ConnectionStrings.ShouldNotBeNull();
role.ConnectionStrings.Any().ShouldBeTrue();
}
[Fact]
public async Task Should_Eager_Load_Tenant_Collections()
{
var role = await TenantRepository.FindByNameAsync("acme");
role.ConnectionStrings.ShouldNotBeNull();
role.ConnectionStrings.Any().ShouldBeTrue();
}
}

Loading…
Cancel
Save