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> <a class="nav-link" href="/blog/abp/">Blog</a>
</li> </li>
<li class="nav-item"> <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>
<li class="for-mobile"> <li class="for-mobile">
<button type="button" class="close close-mmenu" aria-label="Close"> <button type="button" class="close close-mmenu" aria-label="Close">

1
build-all.ps1

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

2
common.props

@ -1,7 +1,7 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Version>0.14.0</Version> <Version>0.15.0</Version>
<NoWarn>$(NoWarn);CS1591</NoWarn> <NoWarn>$(NoWarn);CS1591</NoWarn>
<PackageIconUrl>https://abp.io/assets/abp_nupkg.png</PackageIconUrl> <PackageIconUrl>https://abp.io/assets/abp_nupkg.png</PackageIconUrl>
<PackageProjectUrl>https://abp.io</PackageProjectUrl> <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/) 来**部署**&**运行**所有的服务和应用程序. * 使用 [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/)写日志). * 使用 [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-2.png)
![microservice-sample-diagram](../images/microservice-sample-diagram.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_ProductManagement**: 一个SQL数据库. 同样默认使用 **SQL Server**,但可以是EF Core支持的任何DBMS. 由ProductService用作专用数据库.
* **MsDemo_Blogging**: **MongoDB**数据库. 由BloggingService使用. * **MsDemo_Blogging**: **MongoDB**数据库. 由BloggingService使用.
* **Elasticsearch**: 用于在Serilog上写日志. * **Elasticsearch**: 用于在Serilog上写日志.

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

@ -91,7 +91,7 @@ public class BookStoreDbContext : AbpDbContext<BookStoreDbContext>
#### 添加新的Migration并更新数据库 #### 添加新的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) ![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 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}" 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 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 EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.ObjectMapping", "src\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj", "{8D22063D-88DE-4F7A-A917-C81AB4ACE601}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.ObjectMapping", "src\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj", "{8D22063D-88DE-4F7A-A917-C81AB4ACE601}"
EndProject EndProject
@ -213,7 +213,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.Con
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Features", "src\Volo.Abp.Features\Volo.Abp.Features.csproj", "{01E3D389-8872-4EB1-9D3D-13B6ED54DE0E}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Features", "src\Volo.Abp.Features\Volo.Abp.Features.csproj", "{01E3D389-8872-4EB1-9D3D-13B6ED54DE0E}"
EndProject 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 EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution

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

@ -15,7 +15,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore\Volo.Abp.AspNetCore.csproj" /> <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> </ItemGroup>
</Project> </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 namespace Volo.Abp.AspNetCore.MultiTenancy
{ {
[DependsOn( [DependsOn(
typeof(AbpMultiTenancyAbstractionsModule), typeof(AbpMultiTenancyModule),
typeof(AbpAspNetCoreModule) typeof(AbpAspNetCoreModule)
)] )]
public class AbpAspNetCoreMultiTenancyModule : AbpModule 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 class CookieTenantResolveContributor : HttpTenantResolveContributorBase
{ {
public const string ContributorName = "Cookie";
public override string Name => ContributorName;
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext) protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
{ {
return httpContext.Request?.Cookies[context.GetAspNetCoreMultiTenancyOptions().TenantKey]; 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 class DomainTenantResolveContributor : HttpTenantResolveContributorBase
{ {
public const string ContributorName = "Domain";
public override string Name => ContributorName;
private static readonly string[] ProtocolPrefixes = { "http://", "https://" };
private readonly string _domainFormat; private readonly string _domainFormat;
public DomainTenantResolveContributor(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) if (httpContext.Request?.Host == null)
{ {
return 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); var extractResult = FormattedStringValueExtracter.Extract(hostName, _domainFormat, ignoreCase: true);
context.Handled = true;
if (!extractResult.IsMatch) if (!extractResult.IsMatch)
{ {
return null; 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 class HeaderTenantResolveContributor : HttpTenantResolveContributorBase
{ {
public const string ContributorName = "Header";
public override string Name => ContributorName;
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext) protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
{ {
if (httpContext.Request == null || httpContext.Request.Headers.IsNullOrEmpty()) 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 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(); var httpContext = context.GetHttpContext();
if (httpContext == null) 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;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
@ -12,46 +11,48 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
private readonly ITenantResolver _tenantResolver; private readonly ITenantResolver _tenantResolver;
private readonly ITenantStore _tenantStore; private readonly ITenantStore _tenantStore;
private readonly ICurrentTenantIdAccessor _currentTenantIdAccessor; private readonly ICurrentTenant _currentTenant;
private readonly ITenantResolveResultAccessor _tenantResolveResultAccessor;
public MultiTenancyMiddleware( public MultiTenancyMiddleware(
RequestDelegate next, RequestDelegate next,
ITenantResolver tenantResolver, ITenantResolver tenantResolver,
ITenantStore tenantStore, ITenantStore tenantStore,
ICurrentTenantIdAccessor currentTenantIdAccessor) ICurrentTenant currentTenant,
ITenantResolveResultAccessor tenantResolveResultAccessor)
{ {
_next = next; _next = next;
_tenantResolver = tenantResolver; _tenantResolver = tenantResolver;
_tenantStore = tenantStore; _tenantStore = tenantStore;
_currentTenantIdAccessor = currentTenantIdAccessor; _currentTenant = currentTenant;
_tenantResolveResultAccessor = tenantResolveResultAccessor;
} }
public async Task Invoke(HttpContext httpContext) public async Task Invoke(HttpContext httpContext)
{ {
using (SetCurrentTenant(await ResolveCurrentTenantAsync())) var resolveResult = _tenantResolver.ResolveTenantIdOrName();
{ _tenantResolveResultAccessor.Result = resolveResult;
await _next(httpContext);
}
}
private async Task<TenantInfo> ResolveCurrentTenantAsync() TenantConfiguration tenant = null;
{ if (resolveResult.TenantIdOrName != null)
var tenantIdOrName = _tenantResolver.ResolveTenantIdOrName();
if (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); using (_currentTenant.Change(tenant?.Id, tenant?.Name))
if (tenant == null)
{ {
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)) if (Guid.TryParse(tenantIdOrName, out var parsedTenantId))
{ {
@ -62,15 +63,5 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
return await _tenantStore.FindAsync(tenantIdOrName); 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 class QueryStringTenantResolveContributor : HttpTenantResolveContributorBase
{ {
public const string ContributorName = "QueryString";
public override string Name => ContributorName;
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext) protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
{ {
if (httpContext.Request == null || !httpContext.Request.QueryString.HasValue) 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 class RouteTenantResolveContributor : HttpTenantResolveContributorBase
{ {
public const string ContributorName = "Route";
public override string Name => ContributorName;
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext) protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
{ {
var tenantId = httpContext.GetRouteValue(context.GetAspNetCoreMultiTenancyOptions().TenantKey); 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.Collections.Generic;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Features; 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;
using System.Collections.Generic; using System.Collections.Generic;
using Volo.Abp.Localization;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
{ {
[Serializable] [Serializable]
public class ApplicationLocalizationConfigurationDto public class ApplicationLocalizationConfigurationDto
{ {
//TODO: Rename to Texts?
public Dictionary<string, Dictionary<string, string>> Values { get; set; } public Dictionary<string, Dictionary<string, string>> Values { get; set; }
public List<LanguageInfo> Languages { get; set; }
public ApplicationLocalizationConfigurationDto() public ApplicationLocalizationConfigurationDto()
{ {
Values = new Dictionary<string, Dictionary<string, string>>(); 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'); var tenantSwitchModal = new abp.ModalManager(abp.appPath + 'Abp/MultiTenancy/TenantSwitchModal');
$(function() { $(function() {
$('#TenantSwitchToolbarLink').click(function(e) { $('#AbpTenantSwitchLink').click(function(e) {
e.preventDefault(); e.preventDefault();
tenantSwitchModal.open(); tenantSwitchModal.open();
}); });

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

@ -18,11 +18,9 @@
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Pages\**\*.cshtml" /> <EmbeddedResource Include="Pages\**\*.cshtml" />
<EmbeddedResource Include="Pages\**\*.js" /> <EmbeddedResource Include="Pages\**\*.js" />
<EmbeddedResource Include="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Components\**\*.cshtml" />
<EmbeddedResource Include="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Localization\*.json" /> <EmbeddedResource Include="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Localization\*.json" />
<Content Remove="Pages\**\*.cshtml" /> <Content Remove="Pages\**\*.cshtml" />
<Content Remove="Pages\**\*.js" /> <Content Remove="Pages\**\*.js" />
<Content Remove="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Components\**\*.cshtml" />
<Content Remove="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Localization\*.json" /> <Content Remove="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Localization\*.json" />
</ItemGroup> </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.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling; using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Localization; using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; 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.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
@ -36,11 +34,6 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy
options.FileSets.AddEmbedded<AbpAspNetCoreMvcUiMultiTenancyModule>(); options.FileSets.AddEmbedded<AbpAspNetCoreMvcUiMultiTenancyModule>();
}); });
Configure<ToolbarOptions>(options =>
{
options.Contributors.Add(new MultiTenancyToolbarContributor());
});
Configure<AbpLocalizationOptions>(options => Configure<AbpLocalizationOptions>(options =>
{ {
options.Resources 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", "culture": "en",
"texts": { "texts": {
"GivenTenantIsNotAvailable": "Given tenant is not available: {0}", "GivenTenantIsNotAvailable": "Given tenant is not available: {0}",
"SwitchTenant": "Switch tenant", "Tenant": "Tenant",
"Switch": "switch",
"Name": "Name", "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", "culture": "tr",
"texts": { "texts": {
"GivenTenantIsNotAvailable": "İstenilen müşteri bulunamadı: {0}", "GivenTenantIsNotAvailable": "İstenilen müşteri bulunamadı: {0}",
"SwitchTenant": "Müşteri değiştir", "Tenant": "Müşteri",
"Switch": "değiştir",
"Name": "İsim", "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 ISettingProvider _settingProvider;
private readonly ISettingDefinitionManager _settingDefinitionManager; private readonly ISettingDefinitionManager _settingDefinitionManager;
private readonly IFeatureDefinitionManager _featureDefinitionManager; private readonly IFeatureDefinitionManager _featureDefinitionManager;
private readonly ILanguageProvider _languageProvider;
public AbpApplicationConfigurationAppService( public AbpApplicationConfigurationAppService(
IOptions<AbpLocalizationOptions> localizationOptions, IOptions<AbpLocalizationOptions> localizationOptions,
@ -33,7 +34,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
ICurrentUser currentUser, ICurrentUser currentUser,
ISettingProvider settingProvider, ISettingProvider settingProvider,
SettingDefinitionManager settingDefinitionManager, SettingDefinitionManager settingDefinitionManager,
IFeatureDefinitionManager featureDefinitionManager) IFeatureDefinitionManager featureDefinitionManager,
ILanguageProvider languageProvider)
{ {
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
_abpAuthorizationPolicyProvider = abpAuthorizationPolicyProvider; _abpAuthorizationPolicyProvider = abpAuthorizationPolicyProvider;
@ -42,6 +44,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
_settingProvider = settingProvider; _settingProvider = settingProvider;
_settingDefinitionManager = settingDefinitionManager; _settingDefinitionManager = settingDefinitionManager;
_featureDefinitionManager = featureDefinitionManager; _featureDefinitionManager = featureDefinitionManager;
_languageProvider = languageProvider;
_localizationOptions = localizationOptions.Value; _localizationOptions = localizationOptions.Value;
} }
@ -53,7 +56,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
{ {
Auth = await GetAuthConfigAsync(), Auth = await GetAuthConfigAsync(),
Features = await GetFeaturesConfigAsync(), Features = await GetFeaturesConfigAsync(),
Localization = GetLocalizationConfig(), Localization = await GetLocalizationConfigAsync(),
CurrentUser = GetCurrentUser(), CurrentUser = GetCurrentUser(),
Setting = await GetSettingConfigAsync() Setting = await GetSettingConfigAsync()
}; };
@ -87,10 +90,12 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
return authConfig; return authConfig;
} }
protected virtual ApplicationLocalizationConfigurationDto GetLocalizationConfig() protected virtual async Task<ApplicationLocalizationConfigurationDto> GetLocalizationConfigAsync()
{ {
var localizationConfig = new ApplicationLocalizationConfigurationDto(); var localizationConfig = new ApplicationLocalizationConfigurationDto();
localizationConfig.Languages.AddRange(await _languageProvider.GetLanguagesAsync());
foreach (var resource in _localizationOptions.Resources.Values) foreach (var resource in _localizationOptions.Resources.Values)
{ {
var dictionary = new Dictionary<string, string>(); var dictionary = new Dictionary<string, string>();
@ -104,8 +109,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
dictionary[localizedString.Name] = localizedString.Value; dictionary[localizedString.Name] = localizedString.Value;
} }
var resourceName = LocalizationResourceNameAttribute.GetName(resource.ResourceType); localizationConfig.Values[resource.ResourceName] = dictionary;
localizationConfig.Values[resourceName] = dictionary;
} }
return localizationConfig; return localizationConfig;

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

@ -16,7 +16,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Volo.Abp.Data\Volo.Abp.Data.csproj" /> <ProjectReference Include="..\Volo.Abp.Data\Volo.Abp.Data.csproj" />
<ProjectReference Include="..\Volo.Abp.Json\Volo.Abp.Json.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.Security\Volo.Abp.Security.csproj" />
<ProjectReference Include="..\Volo.Abp.Threading\Volo.Abp.Threading.csproj" /> <ProjectReference Include="..\Volo.Abp.Threading\Volo.Abp.Threading.csproj" />
<ProjectReference Include="..\Volo.Abp.Timing\Volo.Abp.Timing.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(AbpTimingModule),
typeof(AbpSecurityModule), typeof(AbpSecurityModule),
typeof(AbpThreadingModule), typeof(AbpThreadingModule),
typeof(AbpMultiTenancyAbstractionsModule) typeof(AbpMultiTenancyModule)
)] )]
public class AbpAuditingModule : AbpModule public class AbpAuditingModule : AbpModule
{ {

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

@ -19,6 +19,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Volo.Abp.Localization.Abstractions\Volo.Abp.Localization.Abstractions.csproj" /> <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" /> <ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
</ItemGroup> </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.Authorization.Permissions;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Security; using Volo.Abp.Security;
namespace Volo.Abp.Authorization namespace Volo.Abp.Authorization
{ {
[DependsOn( [DependsOn(
typeof(AbpSecurityModule), typeof(AbpSecurityModule),
typeof(AbpLocalizationAbstractionsModule) typeof(AbpLocalizationAbstractionsModule),
typeof(AbpMultiTenancyModule)
)] )]
public class AbpAuthorizationModule : AbpModule public class AbpAuthorizationModule : AbpModule
{ {

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

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

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

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

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

@ -18,7 +18,7 @@
</ItemGroup> </ItemGroup>
<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.Serialization\Volo.Abp.Serialization.csproj" />
<ProjectReference Include="..\Volo.Abp.Threading\Volo.Abp.Threading.csproj" /> <ProjectReference Include="..\Volo.Abp.Threading\Volo.Abp.Threading.csproj" />
</ItemGroup> </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(AbpThreadingModule))]
[DependsOn(typeof(AbpSerializationModule))] [DependsOn(typeof(AbpSerializationModule))]
[DependsOn(typeof(AbpMultiTenancyAbstractionsModule))] [DependsOn(typeof(AbpMultiTenancyModule))]
public class AbpCachingModule : AbpModule public class AbpCachingModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) 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;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.Distributed;
@ -70,11 +69,12 @@ namespace Volo.Abp.Caching
} }
catch (Exception ex) catch (Exception ex)
{ {
if ((bool) hideErrors) if (hideErrors == true)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
return null; return null;
} }
throw; throw;
} }
@ -94,11 +94,14 @@ namespace Volo.Abp.Caching
try try
{ {
cachedBytes = await Cache.GetAsync(NormalizeKey(key), CancellationTokenProvider.FallbackToProvider(token)); cachedBytes = await Cache.GetAsync(
NormalizeKey(key),
CancellationTokenProvider.FallbackToProvider(token)
);
} }
catch (Exception ex) catch (Exception ex)
{ {
if ((bool)hideErrors) if (hideErrors == true)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
return null; return null;
@ -185,7 +188,7 @@ namespace Volo.Abp.Caching
} }
catch (Exception ex) catch (Exception ex)
{ {
if ((bool) hideErrors) if (hideErrors == true)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
return; return;
@ -210,7 +213,7 @@ namespace Volo.Abp.Caching
} }
catch (Exception ex) catch (Exception ex)
{ {
if ((bool)hideErrors) if (hideErrors == true)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
return; return;
@ -230,7 +233,7 @@ namespace Volo.Abp.Caching
} }
catch (Exception ex) catch (Exception ex)
{ {
if ((bool) hideErrors) if (hideErrors == true)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
return; return;
@ -250,7 +253,7 @@ namespace Volo.Abp.Caching
} }
catch (Exception ex) catch (Exception ex)
{ {
if ((bool)hideErrors) if (hideErrors == true)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
return; return;
@ -270,7 +273,7 @@ namespace Volo.Abp.Caching
} }
catch (Exception ex) catch (Exception ex)
{ {
if ((bool) hideErrors) if (hideErrors == true)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
} }
@ -289,7 +292,7 @@ namespace Volo.Abp.Caching
} }
catch (Exception ex) catch (Exception ex)
{ {
if ((bool)hideErrors) if (hideErrors == true)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
return; 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; using Volo.Abp.Modularity;
namespace Volo.Abp.Data namespace Volo.Abp.Data
{ {
public class AbpDataModule : AbpModule public class AbpDataModule : AbpModule
{ {
public override void PreConfigureServices(ServiceConfigurationContext context)
{
AutoAddDataSeedContributors(context.Services);
}
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
var configuration = context.Services.GetConfiguration(); var configuration = context.Services.GetConfiguration();
@ -13,5 +20,23 @@ namespace Volo.Abp.Data
context.Services.AddSingleton(typeof(IDataFilter<>), typeof(DataFilter<>)); 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 namespace Volo.Abp.Data
{ {
//TODO: Create a Volo.Abp.Data.Filtering namespace?
public class DataFilter : IDataFilter, ISingletonDependency public class DataFilter : IDataFilter, ISingletonDependency
{ {
private readonly ConcurrentDictionary<Type, object> _filters; 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.Ddd.Domain\Volo.Abp.Ddd.Domain.csproj" />
<ProjectReference Include="..\Volo.Abp.Features\Volo.Abp.Features.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.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.ObjectMapping\Volo.Abp.ObjectMapping.csproj" />
<ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" /> <ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
<ProjectReference Include="..\Volo.Abp.Settings\Volo.Abp.Settings.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 JetBrains.Annotations;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Aspects; using Volo.Abp.Aspects;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
using Volo.Abp.Authorization; using Volo.Abp.Authorization;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Features; using Volo.Abp.Features;
using Volo.Abp.Guids; using Volo.Abp.Guids;
using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.ObjectMapping; using Volo.Abp.ObjectMapping;
using Volo.Abp.Settings; using Volo.Abp.Settings;
@ -21,8 +23,8 @@ using Volo.Abp.Validation;
namespace Volo.Abp.Application.Services namespace Volo.Abp.Application.Services
{ {
public abstract class ApplicationService : public abstract class ApplicationService :
IApplicationService, IApplicationService,
IAvoidDuplicateCrossCuttingConcerns, IAvoidDuplicateCrossCuttingConcerns,
IValidationEnabled, IValidationEnabled,
IUnitOfWorkEnabled, IUnitOfWorkEnabled,
@ -53,6 +55,22 @@ namespace Volo.Abp.Application.Services
public IFeatureChecker FeatureChecker { get; set; } 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 IUnitOfWork CurrentUnitOfWork => UnitOfWorkManager?.Current;
protected ILogger Logger => _lazyLogger.Value; 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.Data\Volo.Abp.Data.csproj" />
<ProjectReference Include="..\Volo.Abp.EventBus\Volo.Abp.EventBus.csproj" /> <ProjectReference Include="..\Volo.Abp.EventBus\Volo.Abp.EventBus.csproj" />
<ProjectReference Include="..\Volo.Abp.Guids\Volo.Abp.Guids.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.ObjectMapping\Volo.Abp.ObjectMapping.csproj" />
<ProjectReference Include="..\Volo.Abp.Threading\Volo.Abp.Threading.csproj" /> <ProjectReference Include="..\Volo.Abp.Threading\Volo.Abp.Threading.csproj" />
<ProjectReference Include="..\Volo.Abp.Timing\Volo.Abp.Timing.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(AbpDataModule),
typeof(AbpEventBusModule), typeof(AbpEventBusModule),
typeof(AbpGuidsModule), typeof(AbpGuidsModule),
typeof(AbpMultiTenancyAbstractionsModule), typeof(AbpMultiTenancyModule),
typeof(AbpThreadingModule), typeof(AbpThreadingModule),
typeof(AbpTimingModule), typeof(AbpTimingModule),
typeof(AbpUnitOfWorkModule), typeof(AbpUnitOfWorkModule),

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

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

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

@ -10,7 +10,7 @@ namespace Volo.Abp.Features
{ {
[DependsOn( [DependsOn(
typeof(AbpLocalizationAbstractionsModule), typeof(AbpLocalizationAbstractionsModule),
typeof(AbpMultiTenancyAbstractionsModule), typeof(AbpMultiTenancyModule),
typeof(AbpValidationModule) typeof(AbpValidationModule)
)] )]
public class AbpFeaturesModule : AbpModule 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -210,6 +212,9 @@ namespace Volo.Abp.Http.Client.DynamicProxying
//CorrelationId //CorrelationId
requestMessage.Headers.Add(CorrelationIdOptions.HttpHeaderName, CorrelationIdProvider.Get()); 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() 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.Modularity;
using Volo.Abp.Settings; using Volo.Abp.Settings;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
@ -24,9 +23,14 @@ namespace Volo.Abp.Localization
Configure<AbpLocalizationOptions>(options => Configure<AbpLocalizationOptions>(options =>
{ {
options.Resources options
.Add<AbpValidationResource>("en") .Resources
.AddVirtualJson("/Localization/Resources/AbpValidation"); .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> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.MultiTenancy.Abstractions</AssemblyName> <AssemblyName>Volo.Abp.MultiTenancy</AssemblyName>
<PackageId>Volo.Abp.MultiTenancy.Abstractions</PackageId> <PackageId>Volo.Abp.MultiTenancy</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> <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 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; private readonly Action<ITenantResolveContext> _resolveAction;
public ActionTenantResolveContributor([NotNull] Action<ITenantResolveContext> resolveAction) public ActionTenantResolveContributor([NotNull] Action<ITenantResolveContext> resolveAction)
@ -14,7 +18,7 @@ namespace Volo.Abp.MultiTenancy
_resolveAction = resolveAction; _resolveAction = resolveAction;
} }
public void Resolve(ITenantResolveContext context) public override void Resolve(ITenantResolveContext context)
{ {
_resolveAction(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 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; var principal = context.ServiceProvider.GetRequiredService<ICurrentPrincipalAccessor>().Principal;
if (principal?.Identity?.IsAuthenticated != true) if (principal?.Identity?.IsAuthenticated != true)
@ -14,8 +18,11 @@ namespace Volo.Abp.MultiTenancy
return; return;
} }
context.TenantIdOrName = principal.Claims.FirstOrDefault(c => c.Type == AbpClaimTypes.TenantId)?.Value;
context.Handled = true; 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] [CanBeNull]
Guid? Id { get; } 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 public interface ITenantResolveContributor
{ {
string Name { get; }
void Resolve(ITenantResolveContext context); 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> /// <returns>
/// Tenant id, unique name or null (if could not resolve). /// Tenant id, unique name or null (if could not resolve).
/// </returns> /// </returns>
[CanBeNull] [NotNull]
string ResolveTenantIdOrName(); 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 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 namespace Volo.Abp.MultiTenancy
{ {
[Serializable] [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; } 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)); 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;
using System.Linq; using System.Linq;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
@ -17,12 +18,9 @@ namespace Volo.Abp.MultiTenancy
_options = options.Value; _options = options.Value;
} }
public string ResolveTenantIdOrName() public TenantResolveResult ResolveTenantIdOrName()
{ {
if (!_options.TenantResolvers.Any()) var result = new TenantResolveResult();
{
return null;
}
using (var serviceScope = _serviceProvider.CreateScope()) using (var serviceScope = _serviceProvider.CreateScope())
{ {
@ -32,15 +30,17 @@ namespace Volo.Abp.MultiTenancy
{ {
tenantResolver.Resolve(context); tenantResolver.Resolve(context);
result.AppliedResolvers.Add(tenantResolver.Name);
if (context.HasResolvedTenantOrHost()) 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 public static class TenantStoreExtensions
{ {
[CanBeNull] [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)); return AsyncHelper.RunSync(() => tenantStore.FindAsync(name));
} }
[CanBeNull] [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)); return AsyncHelper.RunSync(() => tenantStore.FindAsync(id));
} }

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

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

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

Loading…
Cancel
Save