Browse Source

Merge branch 'Translate' of https://github.com/cnAbp/abp into Translate

pull/980/head
maliming 7 years ago
parent
commit
881c276a5d
  1. 2
      abp_io/src/Volo.AbpWebSite.Web/Pages/Shared/Components/Header/Default.cshtml
  2. 1
      build-all.ps1
  3. 2
      common.props
  4. 9
      docs/zh-Hans/Samples/Microservice-Demo.md
  5. 2
      docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md
  6. BIN
      docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-pmc-add-book-migration-v2.png
  7. BIN
      docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v2.png
  8. BIN
      docs/zh-Hans/images/microservice-sample-diagram-2.png
  9. 4
      framework/Volo.Abp.sln
  10. 2
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo.Abp.AspNetCore.MultiTenancy.csproj
  11. 2
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyModule.cs
  12. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/CookieTenantResolveContributor.cs
  13. 16
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/DomainTenantResolveContributor.cs
  14. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HeaderTenantResolveContributor.cs
  15. 40
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpContextTenantResolveResultAccessor.cs
  16. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpTenantResolveContributerBase.cs
  17. 9
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/ITenantResolveResultAccessor.cs
  18. 51
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs
  19. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/QueryStringTenantResolveContributor.cs
  20. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/RouteTenantResolveContributor.cs
  21. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteFeatureChecker.cs
  22. 23
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteLanguageProvider.cs
  23. 5
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs
  24. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/tenant-switch.js
  25. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.csproj
  26. 9
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/AbpAspNetCoreMvcUiMultiTenancyModule.cs
  27. 17
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/TenantSwitch/Default.cshtml
  28. 51
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/TenantSwitch/TenantSwitchViewComponent.cs
  29. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/_ViewImports.cshtml
  30. 8
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en.json
  31. 6
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/tr.json
  32. 21
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/MultiTenancyToolbarContributor.cs
  33. 14
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs
  34. 2
      framework/src/Volo.Abp.Auditing/Volo.Abp.Auditing.csproj
  35. 2
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingModule.cs
  36. 1
      framework/src/Volo.Abp.Authorization/Volo.Abp.Authorization.csproj
  37. 4
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs
  38. 6
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionDefinitionContext.cs
  39. 19
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs
  40. 8
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinitionContext.cs
  41. 16
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionGroupDefinition.cs
  42. 2
      framework/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj
  43. 2
      framework/src/Volo.Abp.Caching/Volo/Abp/Caching/AbpCachingModule.cs
  44. 23
      framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs
  45. 27
      framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDataModule.cs
  46. 1
      framework/src/Volo.Abp.Data/Volo/Abp/Data/DataFilter.cs
  47. 48
      framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedContext.cs
  48. 9
      framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedContributorList.cs
  49. 12
      framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedOptions.cs
  50. 37
      framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeeder.cs
  51. 13
      framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeederExtensions.cs
  52. 9
      framework/src/Volo.Abp.Data/Volo/Abp/Data/IDataSeedContributor.cs
  53. 9
      framework/src/Volo.Abp.Data/Volo/Abp/Data/IDataSeeder.cs
  54. 1
      framework/src/Volo.Abp.Ddd.Application/Volo.Abp.Ddd.Application.csproj
  55. 28
      framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs
  56. 2
      framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj
  57. 2
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs
  58. 2
      framework/src/Volo.Abp.Features/Volo.Abp.Features.csproj
  59. 2
      framework/src/Volo.Abp.Features/Volo/Abp/Features/AbpFeaturesModule.cs
  60. 5
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs
  61. 14
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationModule.cs
  62. 8
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/DefaultResource.cs
  63. 15
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/AbpMultiTenancyAbstractionsModule.cs
  64. 21
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/AsyncLocalCurrentTenantIdAccessor.cs
  65. 30
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ConfigurationStore/ConfigurationTenantStore.cs
  66. 12
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ConfigurationStore/ConfigurationTenantStoreOptions.cs
  67. 34
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/CurrentTenant.cs
  68. 13
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ICurrentTenantIdAccessor.cs
  69. 18
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantIdWrapper.cs
  70. 4
      framework/src/Volo.Abp.MultiTenancy/Volo.Abp.MultiTenancy.csproj
  71. 23
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AbpMultiTenancyModule.cs
  72. 8
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ActionTenantResolveContributor.cs
  73. 21
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AsyncLocalCurrentTenantAccessor.cs
  74. 27
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/BasicTenantInfo.cs
  75. 29
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ConfigurationStore/DefaultTenantStore.cs
  76. 12
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ConfigurationStore/DefaultTenantStoreOptions.cs
  77. 13
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentClaimsPrincipalTenantResolveContributor.cs
  78. 36
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentTenant.cs
  79. 0
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentTenantExtensions.cs
  80. 5
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ICurrentTenant.cs
  81. 12
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ICurrentTenantAccessor.cs
  82. 0
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/IMultiTenant.cs
  83. 0
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantResolveContext.cs
  84. 2
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantResolveContributor.cs
  85. 4
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantResolver.cs
  86. 4
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantStore.cs
  87. 0
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/IgnoreMultiTenancy.cs
  88. 12
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenancyDatabaseStyle.cs
  89. 17
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenancyOptions.cs
  90. 26
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenancySides.cs
  91. 0
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenantConnectionStringResolver.cs
  92. 10
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfiguration.cs
  93. 0
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveContext.cs
  94. 10
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveContributorBase.cs
  95. 0
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveOptions.cs
  96. 16
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveResult.cs
  97. 18
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolver.cs
  98. 0
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolverConsts.cs
  99. 4
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantStoreExtensions.cs
  100. 2
      framework/src/Volo.Abp.Settings/Volo.Abp.Settings.csproj

2
abp_io/src/Volo.AbpWebSite.Web/Pages/Shared/Components/Header/Default.cshtml

@ -23,7 +23,7 @@
<a class="nav-link" href="/blog/abp/">Blog</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://github.com/abpframework/abp/" target="_blank">Github</a>
<a class="nav-link" href="https://github.com/abpframework/abp/" target="_blank">GitHub</a>
</li>
<li class="for-mobile">
<button type="button" class="close close-mmenu" aria-label="Close">

1
build-all.ps1

@ -9,6 +9,7 @@ $solutionPaths = (
"modules/users",
"modules/permission-management",
"modules/setting-management",
"modules/feature-management",
"modules/identity",
"modules/identityserver",
"modules/tenant-management",

2
common.props

@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Version>0.14.0</Version>
<Version>0.15.0</Version>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<PackageIconUrl>https://abp.io/assets/abp_nupkg.png</PackageIconUrl>
<PackageProjectUrl>https://abp.io</PackageProjectUrl>

9
docs/zh-Hans/Samples/Microservice-Demo.md

@ -22,10 +22,9 @@ ABP框架的主要目标之一就是提供[便捷的基础设施来创建微服
* 使用 [Docker](https://www.docker.com/) & [Kubernates](https://kubernetes.io/) 来**部署**&**运行**所有的服务和应用程序.
* 使用 [Elasticsearch](https://www.elastic.co/products/elasticsearch) & [Kibana](https://www.elastic.co/products/kibana) 来存储和可视化日志 (使用[Serilog](https://serilog.net/)写日志).
下图展示了该系统:
下图显示了该系统:
![microservice-sample-diagram](../images/microservice-sample-diagram.png)
![microservice-sample-diagram](../images/microservice-sample-diagram-2.png)
### 源码
@ -33,7 +32,7 @@ ABP框架的主要目标之一就是提供[便捷的基础设施来创建微服
### 状态
此示例仍处于开发阶段,尚未完成.
该示例的初始版本已完成.其他改进仍在开发中.
## 运行解决方案
@ -176,7 +175,7 @@ Visual Studio解决方案由多个项目组成,每个项目在系统中具有不
此解决方案使用多个数据库:
* **MsDemo_Identity**: 一个SQL数据库. 默认使用** SQL Server **,但可以是EF Core支持的任何DBMS. 由AuthServer和IdentityService共享. 审计日志,权限和设置也存储在此数据库中(虽然它们可以轻松拥有自己的数据库,共享相同的数据库以保持简单).
* **MsDemo_Identity**: 一个SQL数据库. 默认使用**SQL Server**,但可以是EF Core支持的任何DBMS. 由AuthServer和IdentityService共享. 审计日志,权限和设置也存储在此数据库中(虽然它们可以轻松拥有自己的数据库,共享相同的数据库以保持简单).
* **MsDemo_ProductManagement**: 一个SQL数据库. 同样默认使用 **SQL Server**,但可以是EF Core支持的任何DBMS. 由ProductService用作专用数据库.
* **MsDemo_Blogging**: **MongoDB**数据库. 由BloggingService使用.
* **Elasticsearch**: 用于在Serilog上写日志.

2
docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md

@ -91,7 +91,7 @@ public class BookStoreDbContext : AbpDbContext<BookStoreDbContext>
#### 添加新的Migration并更新数据库
这个启动模板使用了[EF Core Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/)来创建并维护数据库结构.打开 **Package Manager Console (PMC)** (工具/Nuget包管理器菜单),选择 `Acme.BookStore.EntityFrameworkCore`作为默认的项目然后执行下面的命令:
这个启动模板使用了[EF Core Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/)来创建并维护数据库结构.打开 **Package Manager Console (PMC)** (工具/Nuget包管理器菜单),选择 `Acme.BookStore.EntityFrameworkCore.DbMigrations`作为默认的项目然后执行下面的命令:
![bookstore-pmc-add-book-migration](images/bookstore-pmc-add-book-migration-v2.png)

BIN
docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-pmc-add-book-migration-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
docs/zh-Hans/images/microservice-sample-diagram-2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

4
framework/Volo.Abp.sln

@ -87,7 +87,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Data", "src\Volo.A
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Data.Tests", "test\Volo.Abp.Data.Tests\Volo.Abp.Data.Tests.csproj", "{5D2275B7-0745-420A-AF1C-32C563DAB5C8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MultiTenancy.Abstractions", "src\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj", "{10EB789E-C993-4BE8-BA43-C419936C7233}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MultiTenancy", "src\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj", "{10EB789E-C993-4BE8-BA43-C419936C7233}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.ObjectMapping", "src\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj", "{8D22063D-88DE-4F7A-A917-C81AB4ACE601}"
EndProject
@ -213,7 +213,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.Con
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Features", "src\Volo.Abp.Features\Volo.Abp.Features.csproj", "{01E3D389-8872-4EB1-9D3D-13B6ED54DE0E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Features.Tests", "test\Volo.Abp.Features.Tests\Volo.Abp.Features.Tests.csproj", "{575BEFA1-19C2-49B1-8D31-B5D4472328DE}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Features.Tests", "test\Volo.Abp.Features.Tests\Volo.Abp.Features.Tests.csproj", "{575BEFA1-19C2-49B1-8D31-B5D4472328DE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

2
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo.Abp.AspNetCore.MultiTenancy.csproj

@ -15,7 +15,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore\Volo.Abp.AspNetCore.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />
</ItemGroup>
</Project>

2
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyModule.cs

@ -5,7 +5,7 @@ using Volo.Abp.MultiTenancy;
namespace Volo.Abp.AspNetCore.MultiTenancy
{
[DependsOn(
typeof(AbpMultiTenancyAbstractionsModule),
typeof(AbpMultiTenancyModule),
typeof(AbpAspNetCoreModule)
)]
public class AbpAspNetCoreMultiTenancyModule : AbpModule

4
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/CookieTenantResolveContributor.cs

@ -5,6 +5,10 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
{
public class CookieTenantResolveContributor : HttpTenantResolveContributorBase
{
public const string ContributorName = "Cookie";
public override string Name => ContributorName;
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
{
return httpContext.Request?.Cookies[context.GetAspNetCoreMultiTenancyOptions().TenantKey];

16
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/DomainTenantResolveContributor.cs

@ -9,23 +9,33 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
public class DomainTenantResolveContributor : HttpTenantResolveContributorBase
{
public const string ContributorName = "Domain";
public override string Name => ContributorName;
private static readonly string[] ProtocolPrefixes = { "http://", "https://" };
private readonly string _domainFormat;
public DomainTenantResolveContributor(string domainFormat)
{
_domainFormat = domainFormat.RemovePreFix("http://", "https://");
_domainFormat = domainFormat.RemovePreFix(ProtocolPrefixes);
}
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
protected override string GetTenantIdOrNameFromHttpContextOrNull(
ITenantResolveContext context,
HttpContext httpContext)
{
if (httpContext.Request?.Host == null)
{
return null;
}
var hostName = httpContext.Request.Host.Host.RemovePreFix("http://", "https://");
var hostName = httpContext.Request.Host.Host.RemovePreFix(ProtocolPrefixes);
var extractResult = FormattedStringValueExtracter.Extract(hostName, _domainFormat, ignoreCase: true);
context.Handled = true;
if (!extractResult.IsMatch)
{
return null;

4
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HeaderTenantResolveContributor.cs

@ -9,6 +9,10 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
{
public class HeaderTenantResolveContributor : HttpTenantResolveContributorBase
{
public const string ContributorName = "Header";
public override string Name => ContributorName;
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
{
if (httpContext.Request == null || httpContext.Request.Headers.IsNullOrEmpty())

40
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpContextTenantResolveResultAccessor.cs

@ -0,0 +1,40 @@
using JetBrains.Annotations;
using Microsoft.AspNetCore.Http;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.AspNetCore.MultiTenancy
{
public class HttpContextTenantResolveResultAccessor : ITenantResolveResultAccessor, ITransientDependency
{
[CanBeNull]
public TenantResolveResult Result
{
get
{
if (_httpContextAccessor.HttpContext == null)
{
return null;
}
return _httpContextAccessor.HttpContext.Items[""] as TenantResolveResult;
}
set
{
if (_httpContextAccessor.HttpContext == null)
{
return;
}
_httpContextAccessor.HttpContext.Items[""] = value;
}
}
private readonly IHttpContextAccessor _httpContextAccessor;
public HttpContextTenantResolveResultAccessor(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
}
}

4
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpTenantResolveContributerBase.cs

@ -7,9 +7,9 @@ using Volo.Abp.MultiTenancy;
namespace Volo.Abp.AspNetCore.MultiTenancy
{
public abstract class HttpTenantResolveContributorBase : ITenantResolveContributor
public abstract class HttpTenantResolveContributorBase : TenantResolveContributorBase
{
public virtual void Resolve(ITenantResolveContext context)
public override void Resolve(ITenantResolveContext context)
{
var httpContext = context.GetHttpContext();
if (httpContext == null)

9
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/ITenantResolveResultAccessor.cs

@ -0,0 +1,9 @@
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.AspNetCore.MultiTenancy
{
public interface ITenantResolveResultAccessor
{
TenantResolveResult Result { get; set; }
}
}

51
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs

@ -1,6 +1,5 @@
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Http;
using Volo.Abp.MultiTenancy;
@ -12,46 +11,48 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
private readonly ITenantResolver _tenantResolver;
private readonly ITenantStore _tenantStore;
private readonly ICurrentTenantIdAccessor _currentTenantIdAccessor;
private readonly ICurrentTenant _currentTenant;
private readonly ITenantResolveResultAccessor _tenantResolveResultAccessor;
public MultiTenancyMiddleware(
RequestDelegate next,
ITenantResolver tenantResolver,
ITenantStore tenantStore,
ICurrentTenantIdAccessor currentTenantIdAccessor)
ICurrentTenant currentTenant,
ITenantResolveResultAccessor tenantResolveResultAccessor)
{
_next = next;
_tenantResolver = tenantResolver;
_tenantStore = tenantStore;
_currentTenantIdAccessor = currentTenantIdAccessor;
_currentTenant = currentTenant;
_tenantResolveResultAccessor = tenantResolveResultAccessor;
}
public async Task Invoke(HttpContext httpContext)
{
using (SetCurrentTenant(await ResolveCurrentTenantAsync()))
{
await _next(httpContext);
}
}
var resolveResult = _tenantResolver.ResolveTenantIdOrName();
_tenantResolveResultAccessor.Result = resolveResult;
private async Task<TenantInfo> ResolveCurrentTenantAsync()
{
var tenantIdOrName = _tenantResolver.ResolveTenantIdOrName();
if (tenantIdOrName == null)
TenantConfiguration tenant = null;
if (resolveResult.TenantIdOrName != null)
{
return null;
tenant = await FindTenantAsync(resolveResult.TenantIdOrName);
if (tenant == null)
{
//TODO: A better exception?
throw new AbpException(
"There is no tenant with given tenant id or name: " + resolveResult.TenantIdOrName
);
}
}
var tenant = await FindTenantAsync(tenantIdOrName);
if (tenant == null)
using (_currentTenant.Change(tenant?.Id, tenant?.Name))
{
throw new AbpException("There is no tenant with given tenant id or name: " + tenantIdOrName);
await _next(httpContext);
}
return tenant;
}
private async Task<TenantInfo> FindTenantAsync(string tenantIdOrName)
private async Task<TenantConfiguration> FindTenantAsync(string tenantIdOrName)
{
if (Guid.TryParse(tenantIdOrName, out var parsedTenantId))
{
@ -62,15 +63,5 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
return await _tenantStore.FindAsync(tenantIdOrName);
}
}
private IDisposable SetCurrentTenant([CanBeNull] TenantInfo tenant)
{
var parentScope = _currentTenantIdAccessor.Current;
_currentTenantIdAccessor.Current = new TenantIdWrapper(tenant?.Id);
return new DisposeAction(() =>
{
_currentTenantIdAccessor.Current = parentScope;
});
}
}
}

4
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/QueryStringTenantResolveContributor.cs

@ -5,6 +5,10 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
{
public class QueryStringTenantResolveContributor : HttpTenantResolveContributorBase
{
public const string ContributorName = "QueryString";
public override string Name => ContributorName;
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
{
if (httpContext.Request == null || !httpContext.Request.QueryString.HasValue)

4
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/RouteTenantResolveContributor.cs

@ -7,6 +7,10 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
{
public class RouteTenantResolveContributor : HttpTenantResolveContributorBase
{
public const string ContributorName = "Route";
public override string Name => ContributorName;
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
{
var tenantId = httpContext.GetRouteValue(context.GetAspNetCoreMultiTenancyOptions().TenantKey);

4
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteFeatureChecker.cs

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Features;

23
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteLanguageProvider.cs

@ -0,0 +1,23 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Localization;
namespace Volo.Abp.AspNetCore.Mvc.Client
{
public class RemoteLanguageProvider : ILanguageProvider, ITransientDependency
{
protected ICachedApplicationConfigurationClient ConfigurationClient { get; }
public RemoteLanguageProvider(ICachedApplicationConfigurationClient configurationClient)
{
ConfigurationClient = configurationClient;
}
public async Task<IReadOnlyList<LanguageInfo>> GetLanguagesAsync()
{
var configuration = await ConfigurationClient.GetAsync();
return configuration.Localization.Languages;
}
}
}

5
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs

@ -1,16 +1,21 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Localization;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
{
[Serializable]
public class ApplicationLocalizationConfigurationDto
{
//TODO: Rename to Texts?
public Dictionary<string, Dictionary<string, string>> Values { get; set; }
public List<LanguageInfo> Languages { get; set; }
public ApplicationLocalizationConfigurationDto()
{
Values = new Dictionary<string, Dictionary<string, string>>();
Languages = new List<LanguageInfo>();
}
}
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/tenant-switch.js

@ -3,7 +3,7 @@
var tenantSwitchModal = new abp.ModalManager(abp.appPath + 'Abp/MultiTenancy/TenantSwitchModal');
$(function() {
$('#TenantSwitchToolbarLink').click(function(e) {
$('#AbpTenantSwitchLink').click(function(e) {
e.preventDefault();
tenantSwitchModal.open();
});

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.csproj

@ -18,11 +18,9 @@
<ItemGroup>
<EmbeddedResource Include="Pages\**\*.cshtml" />
<EmbeddedResource Include="Pages\**\*.js" />
<EmbeddedResource Include="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Components\**\*.cshtml" />
<EmbeddedResource Include="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Localization\*.json" />
<Content Remove="Pages\**\*.cshtml" />
<Content Remove="Pages\**\*.js" />
<Content Remove="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Components\**\*.cshtml" />
<Content Remove="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Localization\*.json" />
</ItemGroup>

9
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/AbpAspNetCoreMvcUiMultiTenancyModule.cs

@ -1,11 +1,9 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
@ -36,11 +34,6 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy
options.FileSets.AddEmbedded<AbpAspNetCoreMvcUiMultiTenancyModule>();
});
Configure<ToolbarOptions>(options =>
{
options.Contributors.Add(new MultiTenancyToolbarContributor());
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources

17
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/TenantSwitch/Default.cshtml

@ -1,17 +0,0 @@
@using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Components.TenantSwitch
@model TenantSwitchViewComponent.TenantSwitchViewModel
@if (!Model.CurrentUser.IsAuthenticated)
{
<li class="nav-item">
<a abp-button="Link" id="TenantSwitchToolbarLink" href="#">
@if (Model.Tenant == null)
{
<text>@@host</text>
}
else
{
<text>@@@Model.Tenant.Name</text>
}
</a>
</li>
}

51
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/TenantSwitch/TenantSwitchViewComponent.cs

@ -1,51 +0,0 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Users;
namespace Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Components.TenantSwitch
{
public class TenantSwitchViewComponent : AbpViewComponent
{
/// <summary>
/// -1,000,000
/// </summary>
public const int Order = -1_000_000;
protected ITenantStore TenantStore { get; }
protected ICurrentTenant CurrentTenant { get; }
protected ICurrentUser CurrentUser { get; }
public TenantSwitchViewComponent(
ITenantStore tenantStore,
ICurrentTenant currentTenant,
ICurrentUser currentUser)
{
TenantStore = tenantStore;
CurrentTenant = currentTenant;
CurrentUser = currentUser;
}
public async Task<IViewComponentResult> InvokeAsync()
{
var model = new TenantSwitchViewModel
{
CurrentUser = CurrentUser
};
if (CurrentTenant.Id.HasValue)
{
model.Tenant = await TenantStore.FindAsync(CurrentTenant.GetId());
}
return View("~/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/TenantSwitch/Default.cshtml", model);
}
public class TenantSwitchViewModel
{
public TenantInfo Tenant { get; set; }
public ICurrentUser CurrentUser { get; set; }
}
}
}

3
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/_ViewImports.cshtml

@ -1,3 +0,0 @@
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling

8
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en.json

@ -1,9 +1,11 @@
{
{
"culture": "en",
"texts": {
"GivenTenantIsNotAvailable": "Given tenant is not available: {0}",
"SwitchTenant": "Switch tenant",
"Tenant": "Tenant",
"Switch": "switch",
"Name": "Name",
"SwitchTenantHint": "Leave the name field blank to switch to the host side."
"SwitchTenantHint": "Leave the name field blank to switch to the host side.",
"NotSelected": "Not selected"
}
}

6
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/tr.json

@ -2,8 +2,10 @@
"culture": "tr",
"texts": {
"GivenTenantIsNotAvailable": "İstenilen müşteri bulunamadı: {0}",
"SwitchTenant": "Müşteri değiştir",
"Tenant": "Müşteri",
"Switch": "değiştir",
"Name": "İsim",
"SwitchTenantHint": "Host tarafına geçmek için isim alanını boş bırakın."
"SwitchTenantHint": "Host tarafına geçmek için isim alanını boş bırakın.",
"NotSelected": "Seçili değil"
}
}

21
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/MultiTenancyToolbarContributor.cs

@ -1,21 +0,0 @@
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Components.TenantSwitch;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars;
namespace Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy
{
public class MultiTenancyToolbarContributor : IToolbarContributor
{
public Task ConfigureToolbarAsync(IToolbarConfigurationContext context)
{
if (context.Toolbar.Name != StandardToolbars.Main)
{
return Task.CompletedTask;
}
context.Toolbar.Items.Add(new ToolbarItem(typeof(TenantSwitchViewComponent), TenantSwitchViewComponent.Order));
return Task.CompletedTask;
}
}
}

14
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs

@ -24,6 +24,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
private readonly ISettingProvider _settingProvider;
private readonly ISettingDefinitionManager _settingDefinitionManager;
private readonly IFeatureDefinitionManager _featureDefinitionManager;
private readonly ILanguageProvider _languageProvider;
public AbpApplicationConfigurationAppService(
IOptions<AbpLocalizationOptions> localizationOptions,
@ -33,7 +34,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
ICurrentUser currentUser,
ISettingProvider settingProvider,
SettingDefinitionManager settingDefinitionManager,
IFeatureDefinitionManager featureDefinitionManager)
IFeatureDefinitionManager featureDefinitionManager,
ILanguageProvider languageProvider)
{
_serviceProvider = serviceProvider;
_abpAuthorizationPolicyProvider = abpAuthorizationPolicyProvider;
@ -42,6 +44,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
_settingProvider = settingProvider;
_settingDefinitionManager = settingDefinitionManager;
_featureDefinitionManager = featureDefinitionManager;
_languageProvider = languageProvider;
_localizationOptions = localizationOptions.Value;
}
@ -53,7 +56,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
{
Auth = await GetAuthConfigAsync(),
Features = await GetFeaturesConfigAsync(),
Localization = GetLocalizationConfig(),
Localization = await GetLocalizationConfigAsync(),
CurrentUser = GetCurrentUser(),
Setting = await GetSettingConfigAsync()
};
@ -87,10 +90,12 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
return authConfig;
}
protected virtual ApplicationLocalizationConfigurationDto GetLocalizationConfig()
protected virtual async Task<ApplicationLocalizationConfigurationDto> GetLocalizationConfigAsync()
{
var localizationConfig = new ApplicationLocalizationConfigurationDto();
localizationConfig.Languages.AddRange(await _languageProvider.GetLanguagesAsync());
foreach (var resource in _localizationOptions.Resources.Values)
{
var dictionary = new Dictionary<string, string>();
@ -104,8 +109,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
dictionary[localizedString.Name] = localizedString.Value;
}
var resourceName = LocalizationResourceNameAttribute.GetName(resource.ResourceType);
localizationConfig.Values[resourceName] = dictionary;
localizationConfig.Values[resource.ResourceName] = dictionary;
}
return localizationConfig;

2
framework/src/Volo.Abp.Auditing/Volo.Abp.Auditing.csproj

@ -16,7 +16,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Data\Volo.Abp.Data.csproj" />
<ProjectReference Include="..\Volo.Abp.Json\Volo.Abp.Json.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />
<ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
<ProjectReference Include="..\Volo.Abp.Threading\Volo.Abp.Threading.csproj" />
<ProjectReference Include="..\Volo.Abp.Timing\Volo.Abp.Timing.csproj" />

2
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingModule.cs

@ -15,7 +15,7 @@ namespace Volo.Abp.Auditing
typeof(AbpTimingModule),
typeof(AbpSecurityModule),
typeof(AbpThreadingModule),
typeof(AbpMultiTenancyAbstractionsModule)
typeof(AbpMultiTenancyModule)
)]
public class AbpAuditingModule : AbpModule
{

1
framework/src/Volo.Abp.Authorization/Volo.Abp.Authorization.csproj

@ -19,6 +19,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Localization.Abstractions\Volo.Abp.Localization.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />
<ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
</ItemGroup>

4
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs

@ -5,13 +5,15 @@ using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Security;
namespace Volo.Abp.Authorization
{
[DependsOn(
typeof(AbpSecurityModule),
typeof(AbpLocalizationAbstractionsModule)
typeof(AbpLocalizationAbstractionsModule),
typeof(AbpMultiTenancyModule)
)]
public class AbpAuthorizationModule : AbpModule
{

6
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionDefinitionContext.cs

@ -1,5 +1,6 @@
using JetBrains.Annotations;
using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Authorization.Permissions
{
@ -8,7 +9,10 @@ namespace Volo.Abp.Authorization.Permissions
//TODO: Add Get methods to find and modify a permission or group.
PermissionGroupDefinition GetGroupOrNull(string name);
PermissionGroupDefinition AddGroup([NotNull] string name, ILocalizableString displayName = null);
PermissionGroupDefinition AddGroup(
[NotNull] string name,
ILocalizableString displayName = null,
MultiTenancySides multiTenancySide = MultiTenancySides.Both);
void RemoveGroup(string name);
}

19
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs

@ -2,6 +2,7 @@
using System.Collections.Immutable;
using JetBrains.Annotations;
using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Authorization.Permissions
{
@ -18,6 +19,12 @@ namespace Volo.Abp.Authorization.Permissions
/// </summary>
public PermissionDefinition Parent { get; private set; }
/// <summary>
/// MultiTenancy side.
/// Default: <see cref="MultiTenancySides.Both"/>
/// </summary>
public MultiTenancySides MultiTenancySide { get; set; }
/// <summary>
/// A list of allowed providers to get/set value of this permission.
/// An empty list indicates that all providers are allowed.
@ -55,10 +62,12 @@ namespace Volo.Abp.Authorization.Permissions
protected internal PermissionDefinition(
[NotNull] string name,
ILocalizableString displayName = null)
ILocalizableString displayName = null,
MultiTenancySides multiTenancySide = MultiTenancySides.Both)
{
Name = Check.NotNull(name, nameof(name));
DisplayName = displayName ?? new FixedLocalizableString(name);
MultiTenancySide = multiTenancySide;
Properties = new Dictionary<string, object>();
Providers = new List<string>();
@ -67,9 +76,13 @@ namespace Volo.Abp.Authorization.Permissions
public virtual PermissionDefinition AddChild(
[NotNull] string name,
ILocalizableString displayName = null)
ILocalizableString displayName = null,
MultiTenancySides multiTenancySide = MultiTenancySides.Both)
{
var child = new PermissionDefinition(name, displayName)
var child = new PermissionDefinition(
name,
displayName,
multiTenancySide)
{
Parent = this
};

8
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinitionContext.cs

@ -1,5 +1,6 @@
using System.Collections.Generic;
using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Authorization.Permissions
{
@ -12,7 +13,10 @@ namespace Volo.Abp.Authorization.Permissions
Groups = new Dictionary<string, PermissionGroupDefinition>();
}
public virtual PermissionGroupDefinition AddGroup(string name, ILocalizableString displayName = null)
public virtual PermissionGroupDefinition AddGroup(
string name,
ILocalizableString displayName = null,
MultiTenancySides multiTenancySide = MultiTenancySides.Both)
{
Check.NotNull(name, nameof(name));
@ -21,7 +25,7 @@ namespace Volo.Abp.Authorization.Permissions
throw new AbpException($"There is already an existing permission group with name: {name}");
}
return Groups[name] = new PermissionGroupDefinition(name, displayName);
return Groups[name] = new PermissionGroupDefinition(name, displayName, multiTenancySide);
}
public virtual PermissionGroupDefinition GetGroupOrNull(string name)

16
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionGroupDefinition.cs

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Authorization.Permissions
{
@ -20,6 +21,12 @@ namespace Volo.Abp.Authorization.Permissions
}
private ILocalizableString _displayName;
/// <summary>
/// MultiTenancy side.
/// Default: <see cref="MultiTenancySides.Both"/>
/// </summary>
public MultiTenancySides MultiTenancySide { get; set; }
public IReadOnlyList<PermissionDefinition> Permissions => _permissions.ToImmutableList();
private readonly List<PermissionDefinition> _permissions;
@ -39,10 +46,12 @@ namespace Volo.Abp.Authorization.Permissions
protected internal PermissionGroupDefinition(
string name,
ILocalizableString displayName = null)
ILocalizableString displayName = null,
MultiTenancySides multiTenancySide = MultiTenancySides.Both)
{
Name = name;
DisplayName = displayName ?? new FixedLocalizableString(Name);
MultiTenancySide = multiTenancySide;
Properties = new Dictionary<string, object>();
_permissions = new List<PermissionDefinition>();
@ -50,9 +59,10 @@ namespace Volo.Abp.Authorization.Permissions
public virtual PermissionDefinition AddPermission(
string name,
ILocalizableString displayName = null)
ILocalizableString displayName = null,
MultiTenancySides multiTenancySide = MultiTenancySides.Both)
{
var permission = new PermissionDefinition(name, displayName);
var permission = new PermissionDefinition(name, displayName, multiTenancySide);
_permissions.Add(permission);

2
framework/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj

@ -18,7 +18,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />
<ProjectReference Include="..\Volo.Abp.Serialization\Volo.Abp.Serialization.csproj" />
<ProjectReference Include="..\Volo.Abp.Threading\Volo.Abp.Threading.csproj" />
</ItemGroup>

2
framework/src/Volo.Abp.Caching/Volo/Abp/Caching/AbpCachingModule.cs

@ -9,7 +9,7 @@ namespace Volo.Abp.Caching
{
[DependsOn(typeof(AbpThreadingModule))]
[DependsOn(typeof(AbpSerializationModule))]
[DependsOn(typeof(AbpMultiTenancyAbstractionsModule))]
[DependsOn(typeof(AbpMultiTenancyModule))]
public class AbpCachingModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)

23
framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs

@ -1,5 +1,4 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed;
@ -70,11 +69,12 @@ namespace Volo.Abp.Caching
}
catch (Exception ex)
{
if ((bool) hideErrors)
if (hideErrors == true)
{
Logger.LogException(ex, LogLevel.Warning);
return null;
}
throw;
}
@ -94,11 +94,14 @@ namespace Volo.Abp.Caching
try
{
cachedBytes = await Cache.GetAsync(NormalizeKey(key), CancellationTokenProvider.FallbackToProvider(token));
cachedBytes = await Cache.GetAsync(
NormalizeKey(key),
CancellationTokenProvider.FallbackToProvider(token)
);
}
catch (Exception ex)
{
if ((bool)hideErrors)
if (hideErrors == true)
{
Logger.LogException(ex, LogLevel.Warning);
return null;
@ -185,7 +188,7 @@ namespace Volo.Abp.Caching
}
catch (Exception ex)
{
if ((bool) hideErrors)
if (hideErrors == true)
{
Logger.LogException(ex, LogLevel.Warning);
return;
@ -210,7 +213,7 @@ namespace Volo.Abp.Caching
}
catch (Exception ex)
{
if ((bool)hideErrors)
if (hideErrors == true)
{
Logger.LogException(ex, LogLevel.Warning);
return;
@ -230,7 +233,7 @@ namespace Volo.Abp.Caching
}
catch (Exception ex)
{
if ((bool) hideErrors)
if (hideErrors == true)
{
Logger.LogException(ex, LogLevel.Warning);
return;
@ -250,7 +253,7 @@ namespace Volo.Abp.Caching
}
catch (Exception ex)
{
if ((bool)hideErrors)
if (hideErrors == true)
{
Logger.LogException(ex, LogLevel.Warning);
return;
@ -270,7 +273,7 @@ namespace Volo.Abp.Caching
}
catch (Exception ex)
{
if ((bool) hideErrors)
if (hideErrors == true)
{
Logger.LogException(ex, LogLevel.Warning);
}
@ -289,7 +292,7 @@ namespace Volo.Abp.Caching
}
catch (Exception ex)
{
if ((bool)hideErrors)
if (hideErrors == true)
{
Logger.LogException(ex, LogLevel.Warning);
return;

27
framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDataModule.cs

@ -1,10 +1,17 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
namespace Volo.Abp.Data
{
public class AbpDataModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
AutoAddDataSeedContributors(context.Services);
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
@ -13,5 +20,23 @@ namespace Volo.Abp.Data
context.Services.AddSingleton(typeof(IDataFilter<>), typeof(DataFilter<>));
}
private static void AutoAddDataSeedContributors(IServiceCollection services)
{
var contributors = new List<Type>();
services.OnRegistred(context =>
{
if (typeof(IDataSeedContributor).IsAssignableFrom(context.ImplementationType))
{
contributors.Add(context.ImplementationType);
}
});
services.Configure<DataSeedOptions>(options =>
{
options.Contributors.AddIfNotContains(contributors);
});
}
}
}

1
framework/src/Volo.Abp.Data/Volo/Abp/Data/DataFilter.cs

@ -8,6 +8,7 @@ using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Data
{
//TODO: Create a Volo.Abp.Data.Filtering namespace?
public class DataFilter : IDataFilter, ISingletonDependency
{
private readonly ConcurrentDictionary<Type, object> _filters;

48
framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedContext.cs

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
namespace Volo.Abp.Data
{
public class DataSeedContext
{
public Guid? TenantId { get; set; }
/// <summary>
/// Gets/sets a key-value on the <see cref="Properties"/>.
/// </summary>
/// <param name="name">Name of the property</param>
/// <returns>
/// Returns the value in the <see cref="Properties"/> dictionary by given <see cref="name"/>.
/// Returns null if given <see cref="name"/> is not present in the <see cref="Properties"/> dictionary.
/// </returns>
[CanBeNull]
public object this[string name]
{
get => Properties.GetOrDefault(name);
set => Properties[name] = value;
}
/// <summary>
/// Can be used to get/set custom properties.
/// </summary>
[NotNull]
public Dictionary<string, object> Properties { get; }
public DataSeedContext(Guid? tenantId = null)
{
TenantId = tenantId;
Properties = new Dictionary<string, object>();
}
/// <summary>
/// Sets a property in the <see cref="Properties"/> dictionary.
/// This is a shortcut for nested calls on this object.
/// </summary>
public virtual DataSeedContext WithProperty(string key, object value)
{
Properties[key] = value;
return this;
}
}
}

9
framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedContributorList.cs

@ -0,0 +1,9 @@
using Volo.Abp.Collections;
namespace Volo.Abp.Data
{
public class DataSeedContributorList : TypeList<IDataSeedContributor>
{
}
}

12
framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedOptions.cs

@ -0,0 +1,12 @@
namespace Volo.Abp.Data
{
public class DataSeedOptions
{
public DataSeedContributorList Contributors { get; }
public DataSeedOptions()
{
Contributors = new DataSeedContributorList();
}
}
}

37
framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeeder.cs

@ -0,0 +1,37 @@
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Data
{
//TODO: Create a Volo.Abp.Data.Seeding namespace?
public class DataSeeder : IDataSeeder, ITransientDependency
{
protected IHybridServiceScopeFactory ServiceScopeFactory { get; }
protected DataSeedOptions Options { get; }
public DataSeeder(
IOptions<DataSeedOptions> options,
IHybridServiceScopeFactory serviceScopeFactory)
{
ServiceScopeFactory = serviceScopeFactory;
Options = options.Value;
}
public async Task SeedAsync(DataSeedContext context)
{
using (var scope = ServiceScopeFactory.CreateScope())
{
foreach (var contributorType in Options.Contributors)
{
var contributor = (IDataSeedContributor) scope
.ServiceProvider
.GetRequiredService(contributorType);
await contributor.SeedAsync(context);
}
}
}
}
}

13
framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeederExtensions.cs

@ -0,0 +1,13 @@
using System;
using System.Threading.Tasks;
namespace Volo.Abp.Data
{
public static class DataSeederExtensions
{
public static Task SeedAsync(this IDataSeeder seeder, Guid? tenantId = null)
{
return seeder.SeedAsync(new DataSeedContext(tenantId));
}
}
}

9
framework/src/Volo.Abp.Data/Volo/Abp/Data/IDataSeedContributor.cs

@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace Volo.Abp.Data
{
public interface IDataSeedContributor
{
Task SeedAsync(DataSeedContext context);
}
}

9
framework/src/Volo.Abp.Data/Volo/Abp/Data/IDataSeeder.cs

@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace Volo.Abp.Data
{
public interface IDataSeeder
{
Task SeedAsync(DataSeedContext context);
}
}

1
framework/src/Volo.Abp.Ddd.Application/Volo.Abp.Ddd.Application.csproj

@ -19,6 +19,7 @@
<ProjectReference Include="..\Volo.Abp.Ddd.Domain\Volo.Abp.Ddd.Domain.csproj" />
<ProjectReference Include="..\Volo.Abp.Features\Volo.Abp.Features.csproj" />
<ProjectReference Include="..\Volo.Abp.Http.Abstractions\Volo.Abp.Http.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.Localization\Volo.Abp.Localization.csproj" />
<ProjectReference Include="..\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" />
<ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
<ProjectReference Include="..\Volo.Abp.Settings\Volo.Abp.Settings.csproj" />

28
framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs

@ -1,16 +1,18 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Aspects;
using Volo.Abp.Auditing;
using Volo.Abp.Authorization;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Features;
using Volo.Abp.Guids;
using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy;
using Volo.Abp.ObjectMapping;
using Volo.Abp.Settings;
@ -21,8 +23,8 @@ using Volo.Abp.Validation;
namespace Volo.Abp.Application.Services
{
public abstract class ApplicationService :
IApplicationService,
public abstract class ApplicationService :
IApplicationService,
IAvoidDuplicateCrossCuttingConcerns,
IValidationEnabled,
IUnitOfWorkEnabled,
@ -53,6 +55,22 @@ namespace Volo.Abp.Application.Services
public IFeatureChecker FeatureChecker { get; set; }
public IStringLocalizerFactory StringLocalizerFactory { get; set; }
public IStringLocalizer L => _localizer ?? (_localizer = StringLocalizerFactory.Create(LocalizationResource));
private IStringLocalizer _localizer;
protected Type LocalizationResource
{
get => _localizationResource;
set
{
_localizationResource = value;
_localizer = null;
}
}
private Type _localizationResource = typeof(DefaultResource);
protected IUnitOfWork CurrentUnitOfWork => UnitOfWorkManager?.Current;
protected ILogger Logger => _lazyLogger.Value;

2
framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj

@ -18,7 +18,7 @@
<ProjectReference Include="..\Volo.Abp.Data\Volo.Abp.Data.csproj" />
<ProjectReference Include="..\Volo.Abp.EventBus\Volo.Abp.EventBus.csproj" />
<ProjectReference Include="..\Volo.Abp.Guids\Volo.Abp.Guids.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />
<ProjectReference Include="..\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" />
<ProjectReference Include="..\Volo.Abp.Threading\Volo.Abp.Threading.csproj" />
<ProjectReference Include="..\Volo.Abp.Timing\Volo.Abp.Timing.csproj" />

2
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs

@ -16,7 +16,7 @@ namespace Volo.Abp.Domain
typeof(AbpDataModule),
typeof(AbpEventBusModule),
typeof(AbpGuidsModule),
typeof(AbpMultiTenancyAbstractionsModule),
typeof(AbpMultiTenancyModule),
typeof(AbpThreadingModule),
typeof(AbpTimingModule),
typeof(AbpUnitOfWorkModule),

2
framework/src/Volo.Abp.Features/Volo.Abp.Features.csproj

@ -15,7 +15,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Localization.Abstractions\Volo.Abp.Localization.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />
<ProjectReference Include="..\Volo.Abp.Validation\Volo.Abp.Validation.csproj" />
</ItemGroup>

2
framework/src/Volo.Abp.Features/Volo/Abp/Features/AbpFeaturesModule.cs

@ -10,7 +10,7 @@ namespace Volo.Abp.Features
{
[DependsOn(
typeof(AbpLocalizationAbstractionsModule),
typeof(AbpMultiTenancyAbstractionsModule),
typeof(AbpMultiTenancyModule),
typeof(AbpValidationModule)
)]
public class AbpFeaturesModule : AbpModule

5
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs

@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
@ -210,6 +212,9 @@ namespace Volo.Abp.Http.Client.DynamicProxying
//CorrelationId
requestMessage.Headers.Add(CorrelationIdOptions.HttpHeaderName, CorrelationIdProvider.Get());
//TODO: Is that the way we want? Couldn't send the culture (not ui culture)
requestMessage.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(CultureInfo.CurrentUICulture.Name));
}
private string GetConfiguredApiVersion()

14
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationModule.cs

@ -1,5 +1,4 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Localization.Resources.AbpValidation;
using Volo.Abp.Localization.Resources.AbpValidation;
using Volo.Abp.Modularity;
using Volo.Abp.Settings;
using Volo.Abp.VirtualFileSystem;
@ -24,9 +23,14 @@ namespace Volo.Abp.Localization
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<AbpValidationResource>("en")
.AddVirtualJson("/Localization/Resources/AbpValidation");
options
.Resources
.Add<DefaultResource>("en");
options
.Resources
.Add<AbpValidationResource>("en")
.AddVirtualJson("/Localization/Resources/AbpValidation");
});
}
}

8
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/DefaultResource.cs

@ -0,0 +1,8 @@
namespace Volo.Abp.Localization
{
[LocalizationResourceName("Default")]
public class DefaultResource
{
}
}

15
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/AbpMultiTenancyAbstractionsModule.cs

@ -1,15 +0,0 @@
using Volo.Abp.Data;
using Volo.Abp.Modularity;
using Volo.Abp.Security;
namespace Volo.Abp.MultiTenancy
{
[DependsOn(
typeof(AbpDataModule),
typeof(AbpSecurityModule)
)]
public class AbpMultiTenancyAbstractionsModule : AbpModule //TODO: Rename to AbpMultiTenancyModule?
{
}
}

21
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/AsyncLocalCurrentTenantIdAccessor.cs

@ -1,21 +0,0 @@
using System.Threading;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MultiTenancy
{
public class AsyncLocalCurrentTenantIdAccessor : ICurrentTenantIdAccessor, ISingletonDependency
{
public TenantIdWrapper Current
{
get => _currentScope.Value;
set => _currentScope.Value = value;
}
private readonly AsyncLocal<TenantIdWrapper> _currentScope;
public AsyncLocalCurrentTenantIdAccessor()
{
_currentScope = new AsyncLocal<TenantIdWrapper>();
}
}
}

30
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ConfigurationStore/ConfigurationTenantStore.cs

@ -1,30 +0,0 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MultiTenancy.ConfigurationStore
{
//TODO: Move to another package.
[Dependency(TryRegister = true)]
public class ConfigurationTenantStore : ITenantStore, ITransientDependency
{
private readonly ConfigurationTenantStoreOptions _options;
public ConfigurationTenantStore(IOptionsSnapshot<ConfigurationTenantStoreOptions> options)
{
_options = options.Value;
}
public Task<TenantInfo> FindAsync(string name)
{
return Task.FromResult(_options.Tenants.FirstOrDefault(t => t.Name == name));
}
public Task<TenantInfo> FindAsync(Guid id)
{
return Task.FromResult(_options.Tenants.FirstOrDefault(t => t.Id == id));
}
}
}

12
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ConfigurationStore/ConfigurationTenantStoreOptions.cs

@ -1,12 +0,0 @@
namespace Volo.Abp.MultiTenancy.ConfigurationStore
{
public class ConfigurationTenantStoreOptions
{
public TenantInfo[] Tenants { get; set; }
public ConfigurationTenantStoreOptions()
{
Tenants = new TenantInfo[0];
}
}
}

34
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/CurrentTenant.cs

@ -1,34 +0,0 @@
using System;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MultiTenancy
{
public class CurrentTenant : ICurrentTenant, ITransientDependency
{
public virtual bool IsAvailable => Id.HasValue;
public virtual Guid? Id => _currentTenantIdAccessor.Current?.TenantId;
private readonly ICurrentTenantIdAccessor _currentTenantIdAccessor;
public CurrentTenant(ICurrentTenantIdAccessor currentTenantIdAccessor)
{
_currentTenantIdAccessor = currentTenantIdAccessor;
}
public IDisposable Change(Guid? id)
{
return SetCurrent(id);
}
private IDisposable SetCurrent(Guid? tenantId)
{
var parentScope = _currentTenantIdAccessor.Current;
_currentTenantIdAccessor.Current = new TenantIdWrapper(tenantId);
return new DisposeAction(() =>
{
_currentTenantIdAccessor.Current = parentScope;
});
}
}
}

13
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ICurrentTenantIdAccessor.cs

@ -1,13 +0,0 @@
namespace Volo.Abp.MultiTenancy
{
/* Uses TenantScopeTenantInfoWrapper instead of TenantInfo because being null of Current is different that being null of Current.Tenant.
* A null Current indicates that we haven't set it explicitly.
* A null Current.Tenant indicates that we have set null tenant value explicitly.
* A non-null Current.Tenant indicates that we have set a tenant value explicitly.
*/
public interface ICurrentTenantIdAccessor
{
TenantIdWrapper Current { get; set; }
}
}

18
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantIdWrapper.cs

@ -1,18 +0,0 @@
using System;
namespace Volo.Abp.MultiTenancy
{
public class TenantIdWrapper
{
/// <summary>
/// Null indicates the host.
/// Not null value for a tenant.
/// </summary>
public Guid? TenantId { get; }
public TenantIdWrapper(Guid? tenantId)
{
TenantId = tenantId;
}
}
}

4
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo.Abp.MultiTenancy.Abstractions.csproj → framework/src/Volo.Abp.MultiTenancy/Volo.Abp.MultiTenancy.csproj

@ -4,8 +4,8 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.MultiTenancy.Abstractions</AssemblyName>
<PackageId>Volo.Abp.MultiTenancy.Abstractions</PackageId>
<AssemblyName>Volo.Abp.MultiTenancy</AssemblyName>
<PackageId>Volo.Abp.MultiTenancy</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>

23
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AbpMultiTenancyModule.cs

@ -0,0 +1,23 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Data;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy.ConfigurationStore;
using Volo.Abp.Security;
namespace Volo.Abp.MultiTenancy
{
//TODO: Create a Volo.Abp.MultiTenancy.Abstractions package?
[DependsOn(
typeof(AbpDataModule),
typeof(AbpSecurityModule)
)]
public class AbpMultiTenancyModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<DefaultTenantStoreOptions>(configuration);
}
}
}

8
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ActionTenantResolveContributor.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ActionTenantResolveContributor.cs

@ -3,8 +3,12 @@ using JetBrains.Annotations;
namespace Volo.Abp.MultiTenancy
{
public class ActionTenantResolveContributor : ITenantResolveContributor
public class ActionTenantResolveContributor : TenantResolveContributorBase
{
public const string ContributorName = "Action";
public override string Name => ContributorName;
private readonly Action<ITenantResolveContext> _resolveAction;
public ActionTenantResolveContributor([NotNull] Action<ITenantResolveContext> resolveAction)
@ -14,7 +18,7 @@ namespace Volo.Abp.MultiTenancy
_resolveAction = resolveAction;
}
public void Resolve(ITenantResolveContext context)
public override void Resolve(ITenantResolveContext context)
{
_resolveAction(context);
}

21
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AsyncLocalCurrentTenantAccessor.cs

@ -0,0 +1,21 @@
using System.Threading;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MultiTenancy
{
public class AsyncLocalCurrentTenantAccessor : ICurrentTenantAccessor, ISingletonDependency
{
public BasicTenantInfo Current
{
get => _currentScope.Value;
set => _currentScope.Value = value;
}
private readonly AsyncLocal<BasicTenantInfo> _currentScope;
public AsyncLocalCurrentTenantAccessor()
{
_currentScope = new AsyncLocal<BasicTenantInfo>();
}
}
}

27
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/BasicTenantInfo.cs

@ -0,0 +1,27 @@
using System;
using JetBrains.Annotations;
namespace Volo.Abp.MultiTenancy
{
public class BasicTenantInfo
{
/// <summary>
/// Null indicates the host.
/// Not null value for a tenant.
/// </summary>
[CanBeNull]
public Guid? TenantId { get; }
/// <summary>
/// Name of the tenant if <see cref="TenantId"/> is not null.
/// </summary>
[CanBeNull]
public string Name { get; }
public BasicTenantInfo(Guid? tenantId, string name = null)
{
TenantId = tenantId;
Name = name;
}
}
}

29
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ConfigurationStore/DefaultTenantStore.cs

@ -0,0 +1,29 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MultiTenancy.ConfigurationStore
{
[Dependency(TryRegister = true)]
public class DefaultTenantStore : ITenantStore, ITransientDependency
{
private readonly DefaultTenantStoreOptions _options;
public DefaultTenantStore(IOptionsSnapshot<DefaultTenantStoreOptions> options)
{
_options = options.Value;
}
public Task<TenantConfiguration> FindAsync(string name)
{
return Task.FromResult(_options.Tenants?.FirstOrDefault(t => t.Name == name));
}
public Task<TenantConfiguration> FindAsync(Guid id)
{
return Task.FromResult(_options.Tenants?.FirstOrDefault(t => t.Id == id));
}
}
}

12
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ConfigurationStore/DefaultTenantStoreOptions.cs

@ -0,0 +1,12 @@
namespace Volo.Abp.MultiTenancy.ConfigurationStore
{
public class DefaultTenantStoreOptions
{
public TenantConfiguration[] Tenants { get; set; }
public DefaultTenantStoreOptions()
{
Tenants = new TenantConfiguration[0];
}
}
}

13
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/CurrentClaimsPrincipalTenantResolveContributor.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentClaimsPrincipalTenantResolveContributor.cs

@ -4,9 +4,13 @@ using Volo.Abp.Security.Claims;
namespace Volo.Abp.MultiTenancy
{
public class CurrentClaimsPrincipalTenantResolveContributor : ITenantResolveContributor
public class CurrentClaimsPrincipalTenantResolveContributor : TenantResolveContributorBase
{
public void Resolve(ITenantResolveContext context)
public const string ContributorName = "CurrentClaims";
public override string Name => ContributorName;
public override void Resolve(ITenantResolveContext context)
{
var principal = context.ServiceProvider.GetRequiredService<ICurrentPrincipalAccessor>().Principal;
if (principal?.Identity?.IsAuthenticated != true)
@ -14,8 +18,11 @@ namespace Volo.Abp.MultiTenancy
return;
}
context.TenantIdOrName = principal.Claims.FirstOrDefault(c => c.Type == AbpClaimTypes.TenantId)?.Value;
context.Handled = true;
context.TenantIdOrName = principal
.Claims
.FirstOrDefault(c => c.Type == AbpClaimTypes.TenantId)
?.Value;
}
}
}

36
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentTenant.cs

@ -0,0 +1,36 @@
using System;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MultiTenancy
{
public class CurrentTenant : ICurrentTenant, ITransientDependency
{
public virtual bool IsAvailable => Id.HasValue;
public virtual Guid? Id => _currentTenantAccessor.Current?.TenantId;
public string Name => _currentTenantAccessor.Current?.Name;
private readonly ICurrentTenantAccessor _currentTenantAccessor;
public CurrentTenant(ICurrentTenantAccessor currentTenantAccessor)
{
_currentTenantAccessor = currentTenantAccessor;
}
public IDisposable Change(Guid? id, string name = null)
{
return SetCurrent(id, name);
}
private IDisposable SetCurrent(Guid? tenantId, string name = null)
{
var parentScope = _currentTenantAccessor.Current;
_currentTenantAccessor.Current = new BasicTenantInfo(tenantId, name);
return new DisposeAction(() =>
{
_currentTenantAccessor.Current = parentScope;
});
}
}
}

0
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/CurrentTenantExtensions.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentTenantExtensions.cs

5
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ICurrentTenant.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ICurrentTenant.cs

@ -10,6 +10,9 @@ namespace Volo.Abp.MultiTenancy
[CanBeNull]
Guid? Id { get; }
IDisposable Change(Guid? id);
[CanBeNull]
string Name { get; }
IDisposable Change(Guid? id, string name = null);
}
}

12
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ICurrentTenantAccessor.cs

@ -0,0 +1,12 @@
namespace Volo.Abp.MultiTenancy
{
/* A null Current indicates that we haven't set it explicitly.
* A null Current.TenantId indicates that we have set null tenant id value explicitly.
* A non-null Current.TenantId indicates that we have set a tenant id value explicitly.
*/
public interface ICurrentTenantAccessor
{
BasicTenantInfo Current { get; set; }
}
}

0
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/IMultiTenant.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/IMultiTenant.cs

0
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantResolveContext.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantResolveContext.cs

2
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantResolveContributor.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantResolveContributor.cs

@ -2,6 +2,8 @@ namespace Volo.Abp.MultiTenancy
{
public interface ITenantResolveContributor
{
string Name { get; }
void Resolve(ITenantResolveContext context);
}
}

4
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantResolver.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantResolver.cs

@ -10,7 +10,7 @@ namespace Volo.Abp.MultiTenancy
/// <returns>
/// Tenant id, unique name or null (if could not resolve).
/// </returns>
[CanBeNull]
string ResolveTenantIdOrName();
[NotNull]
TenantResolveResult ResolveTenantIdOrName();
}
}

4
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantStore.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantStore.cs

@ -5,8 +5,8 @@ namespace Volo.Abp.MultiTenancy
{
public interface ITenantStore
{
Task<TenantInfo> FindAsync(string name);
Task<TenantConfiguration> FindAsync(string name);
Task<TenantInfo> FindAsync(Guid id);
Task<TenantConfiguration> FindAsync(Guid id);
}
}

0
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/IgnoreMultiTenancy.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/IgnoreMultiTenancy.cs

12
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenancyDatabaseStyle.cs

@ -0,0 +1,12 @@
using System;
namespace Volo.Abp.MultiTenancy
{
[Flags]
public enum MultiTenancyDatabaseStyle
{
Shared = 1,
PerTenant = 2,
Hybrid = Shared | PerTenant
}
}

17
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenancyOptions.cs

@ -0,0 +1,17 @@
namespace Volo.Abp.MultiTenancy
{
public class MultiTenancyOptions
{
/// <summary>
/// A central point to enable/disable multi-tenancy.
/// Default: false.
/// </summary>
public bool IsEnabled { get; set; }
/// <summary>
/// Database style for tenants.
/// Default: <see cref="MultiTenancyDatabaseStyle.Hybrid"/>.
/// </summary>
public MultiTenancyDatabaseStyle DatabaseStyle { get; set; } = MultiTenancyDatabaseStyle.Hybrid;
}
}

26
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenancySides.cs

@ -0,0 +1,26 @@
using System;
namespace Volo.Abp.MultiTenancy
{
/// <summary>
/// Represents sides in a multi tenancy application.
/// </summary>
[Flags]
public enum MultiTenancySides
{
/// <summary>
/// Tenant side.
/// </summary>
Tenant = 1,
/// <summary>
/// Host side.
/// </summary>
Host = 2,
/// <summary>
/// Both sides
/// </summary>
Both = Tenant | Host
}
}

0
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/MultiTenantConnectionStringResolver.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenantConnectionStringResolver.cs

10
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantInfo.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfiguration.cs

@ -5,20 +5,20 @@ using Volo.Abp.Data;
namespace Volo.Abp.MultiTenancy
{
[Serializable]
public class TenantInfo //TODO: Add a custom data to TenantInfo and make it available in ICurrentTenant
public class TenantConfiguration
{
public Guid Id { get; }
public Guid Id { get; set; }
public string Name { get; }
public string Name { get; set; }
public ConnectionStrings ConnectionStrings { get; }
private TenantInfo()
public TenantConfiguration()
{
}
public TenantInfo(Guid id, [NotNull] string name)
public TenantConfiguration(Guid id, [NotNull] string name)
{
Check.NotNull(name, nameof(name));

0
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantResolveContext.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveContext.cs

10
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveContributorBase.cs

@ -0,0 +1,10 @@
namespace Volo.Abp.MultiTenancy
{
public abstract class TenantResolveContributorBase : ITenantResolveContributor
{
public abstract string Name { get; }
//TODO: We can make this async
public abstract void Resolve(ITenantResolveContext context);
}
}

0
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantResolveOptions.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveOptions.cs

16
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveResult.cs

@ -0,0 +1,16 @@
using System.Collections.Generic;
namespace Volo.Abp.MultiTenancy
{
public class TenantResolveResult
{
public string TenantIdOrName { get; set; }
public List<string> AppliedResolvers { get; }
public TenantResolveResult()
{
AppliedResolvers = new List<string>();
}
}
}

18
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantResolver.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolver.cs

@ -1,5 +1,6 @@
using System;
using System.Linq;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
@ -17,12 +18,9 @@ namespace Volo.Abp.MultiTenancy
_options = options.Value;
}
public string ResolveTenantIdOrName()
public TenantResolveResult ResolveTenantIdOrName()
{
if (!_options.TenantResolvers.Any())
{
return null;
}
var result = new TenantResolveResult();
using (var serviceScope = _serviceProvider.CreateScope())
{
@ -32,15 +30,17 @@ namespace Volo.Abp.MultiTenancy
{
tenantResolver.Resolve(context);
result.AppliedResolvers.Add(tenantResolver.Name);
if (context.HasResolvedTenantOrHost())
{
return context.TenantIdOrName;
result.TenantIdOrName = context.TenantIdOrName;
break;
}
}
//Could not find a tenant
return null;
}
return result;
}
}
}

0
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantResolverConsts.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolverConsts.cs

4
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantStoreExtensions.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantStoreExtensions.cs

@ -7,13 +7,13 @@ namespace Volo.Abp.MultiTenancy
public static class TenantStoreExtensions
{
[CanBeNull]
public static TenantInfo Find(this ITenantStore tenantStore, string name)
public static TenantConfiguration Find(this ITenantStore tenantStore, string name)
{
return AsyncHelper.RunSync(() => tenantStore.FindAsync(name));
}
[CanBeNull]
public static TenantInfo Find(this ITenantStore tenantStore, Guid id)
public static TenantConfiguration Find(this ITenantStore tenantStore, Guid id)
{
return AsyncHelper.RunSync(() => tenantStore.FindAsync(id));
}

2
framework/src/Volo.Abp.Settings/Volo.Abp.Settings.csproj

@ -15,7 +15,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Localization.Abstractions\Volo.Abp.Localization.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />
<ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
</ItemGroup>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save