Browse Source

Introduced ambient tenant and a ChangeTenant method.

pull/81/head
Halil İbrahim Kalkan 9 years ago
parent
commit
1c6a45a175
  1. 7
      Volo.Abp.sln
  2. 19
      src/Volo.Abp.AspNetCore.MultiTenancy/Properties/AssemblyInfo.cs
  3. 20
      src/Volo.Abp.AspNetCore.MultiTenancy/Volo.Abp.AspNetCore.MultiTenancy.xproj
  4. 14
      src/Volo.Abp.AspNetCore.MultiTenancy/project.json
  5. 21
      src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AmbientTenantAccessor.cs
  6. 2
      src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentTenantResolveContext.cs
  7. 22
      src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/IAmbientTenantAccessor.cs
  8. 2
      src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ICurrentTenantResolveContext.cs
  9. 6
      src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/IMultiTenancyManager.cs
  10. 9
      src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantInfo.cs
  11. 25
      src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenancyManager.cs
  12. 2
      src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantInfo.cs
  13. 29
      src/Volo.Abp/Volo/Abp/DisposeAction.cs
  14. 48
      test/Volo.Abp.MultiTenancy.Tests/Volo/Abp/MultiTenancy/MultiTenantManager_TenantResolver_Tests.cs

7
Volo.Abp.sln

@ -46,6 +46,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Volo.Abp.MultiTenancy", "sr
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Volo.Abp.MultiTenancy.Tests", "test\Volo.Abp.MultiTenancy.Tests\Volo.Abp.MultiTenancy.Tests.xproj", "{05271341-7A15-484C-9FD6-802A4193F4DE}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Volo.Abp.AspNetCore.MultiTenancy", "src\Volo.Abp.AspNetCore.MultiTenancy\Volo.Abp.AspNetCore.MultiTenancy.xproj", "{7CC7946B-E026-4F66-8D4F-4F78F4801D43}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -100,6 +102,10 @@ Global
{05271341-7A15-484C-9FD6-802A4193F4DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{05271341-7A15-484C-9FD6-802A4193F4DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{05271341-7A15-484C-9FD6-802A4193F4DE}.Release|Any CPU.Build.0 = Release|Any CPU
{7CC7946B-E026-4F66-8D4F-4F78F4801D43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7CC7946B-E026-4F66-8D4F-4F78F4801D43}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7CC7946B-E026-4F66-8D4F-4F78F4801D43}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7CC7946B-E026-4F66-8D4F-4F78F4801D43}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -122,5 +128,6 @@ Global
{B520B696-86C7-46D2-A359-C2E9013A7BED} = {82B41A0A-6068-410F-9C6B-2508CA763E21}
{58FA9F8F-216D-4C93-8929-D40D22B11CA7} = {4C753F64-0C93-4D65-96C2-A40893AFC1E8}
{05271341-7A15-484C-9FD6-802A4193F4DE} = {37087D1B-3693-4E96-983D-A69F210BDE53}
{7CC7946B-E026-4F66-8D4F-4F78F4801D43} = {4C753F64-0C93-4D65-96C2-A40893AFC1E8}
EndGlobalSection
EndGlobal

19
src/Volo.Abp.AspNetCore.MultiTenancy/Properties/AssemblyInfo.cs

@ -0,0 +1,19 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Volo.Abp.AspNetCore.MultiTenancy")]
[assembly: AssemblyTrademark("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("7cc7946b-e026-4f66-8d4f-4f78f4801d43")]

20
src/Volo.Abp.AspNetCore.MultiTenancy/Volo.Abp.AspNetCore.MultiTenancy.xproj

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>7cc7946b-e026-4f66-8d4f-4f78f4801d43</ProjectGuid>
<RootNamespace>
</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

14
src/Volo.Abp.AspNetCore.MultiTenancy/project.json

@ -0,0 +1,14 @@
{
"version": "1.0.0-*",
"dependencies": {
"NETStandard.Library": "1.6.1",
"Volo.Abp.MultiTenancy": "1.0.0-*"
},
"frameworks": {
"netstandard1.6": {
"imports": "dnxcore50"
}
}
}

21
src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AmbientTenantAccessor.cs

@ -0,0 +1,21 @@
using System.Threading;
using Volo.DependencyInjection;
namespace Volo.Abp.MultiTenancy
{
public class AmbientTenantAccessor : IAmbientTenantAccessor, ISingletonDependency //TODO: Should be IScopedDependency?
{
public AmbientTenantInfo AmbientTenant
{
get { return _tenant.Value; }
set { _tenant.Value = value; }
}
private readonly AsyncLocal<AmbientTenantInfo> _tenant;
public AmbientTenantAccessor()
{
_tenant = new AsyncLocal<AmbientTenantInfo>();
}
}
}

2
src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentTenantResolveContext.cs

@ -2,7 +2,7 @@ namespace Volo.Abp.MultiTenancy
{
public class CurrentTenantResolveContext : ICurrentTenantResolveContext
{
public ITenantInfo Tenant { get; set; }
public TenantInfo Tenant { get; set; }
public bool Handled { get; set; }
}

22
src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/IAmbientTenantAccessor.cs

@ -0,0 +1,22 @@
using JetBrains.Annotations;
namespace Volo.Abp.MultiTenancy
{
public interface IAmbientTenantAccessor
{
AmbientTenantInfo AmbientTenant { get; set; }
}
public class AmbientTenantInfo
{
/// <summary>
/// Null for host.
/// </summary>
public TenantInfo Tenant { get; set; }
public AmbientTenantInfo([CanBeNull] TenantInfo tenant)
{
Tenant = tenant;
}
}
}

2
src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ICurrentTenantResolveContext.cs

@ -2,7 +2,7 @@ namespace Volo.Abp.MultiTenancy
{
public interface ICurrentTenantResolveContext
{
ITenantInfo Tenant { get; set; }
TenantInfo Tenant { get; set; }
bool Handled { get; set; }
}

6
src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/IMultiTenancyManager.cs

@ -1,7 +1,11 @@
using System;
namespace Volo.Abp.MultiTenancy
{
public interface IMultiTenancyManager
{
ITenantInfo CurrentTenant { get; }
TenantInfo CurrentTenant { get; }
IDisposable ChangeTenant(TenantInfo tenantInfo);
}
}

9
src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantInfo.cs

@ -1,9 +0,0 @@
namespace Volo.Abp.MultiTenancy
{
public interface ITenantInfo
{
string Id { get; }
string Name { get; }
}
}

25
src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenancyManager.cs

@ -5,17 +5,24 @@ namespace Volo.Abp.MultiTenancy
{
public class MultiTenancyManager : IMultiTenancyManager
{
public ITenantInfo CurrentTenant => GetCurrentTenant();
public TenantInfo CurrentTenant => GetCurrentTenant();
private readonly IAmbientTenantAccessor _ambientTenantAccessor;
private readonly IEnumerable<ITenantResolver> _currentTenantResolvers;
public MultiTenancyManager(IEnumerable<ITenantResolver> currentTenantResolvers)
public MultiTenancyManager(IAmbientTenantAccessor ambientTenantAccessor, IEnumerable<ITenantResolver> currentTenantResolvers)
{
_ambientTenantAccessor = ambientTenantAccessor;
_currentTenantResolvers = currentTenantResolvers;
}
protected virtual ITenantInfo GetCurrentTenant()
protected virtual TenantInfo GetCurrentTenant()
{
if (_ambientTenantAccessor.AmbientTenant != null)
{
return _ambientTenantAccessor.AmbientTenant.Tenant;
}
var context = new CurrentTenantResolveContext();
foreach (var currentTenantResolver in _currentTenantResolvers)
@ -29,5 +36,17 @@ namespace Volo.Abp.MultiTenancy
return context.Tenant;
}
public IDisposable ChangeTenant(TenantInfo tenantInfo)
{
var oldValue = _ambientTenantAccessor.AmbientTenant;
_ambientTenantAccessor.AmbientTenant = new AmbientTenantInfo(tenantInfo);
return new DisposeAction(() =>
{
_ambientTenantAccessor.AmbientTenant = oldValue;
});
}
}
}

2
src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantInfo.cs

@ -2,7 +2,7 @@ using JetBrains.Annotations;
namespace Volo.Abp.MultiTenancy
{
public class TenantInfo : ITenantInfo
public class TenantInfo
{
public string Id { get; }

29
src/Volo.Abp/Volo/Abp/DisposeAction.cs

@ -0,0 +1,29 @@
using System;
namespace Volo.Abp
{
/// <summary>
/// This class can be used to provide an action when
/// Dipose method is called.
/// </summary>
public class DisposeAction : IDisposable
{
private readonly Action _action;
/// <summary>
/// Creates a new <see cref="DisposeAction"/> object.
/// </summary>
/// <param name="action">Action to be executed when this object is disposed.</param>
public DisposeAction(Action action)
{
Check.NotNull(action, nameof(action));
_action = action;
}
public void Dispose()
{
_action();
}
}
}

48
test/Volo.Abp.MultiTenancy.Tests/Volo/Abp/MultiTenancy/MultiTenantManager_TenantResolver_Tests.cs

@ -1,4 +1,5 @@
using System;
using NSubstitute;
using Shouldly;
using Xunit;
@ -11,9 +12,9 @@ namespace Volo.Abp.MultiTenancy
{
//Arrange
var manager = new MultiTenancyManager(new ITenantResolver[0]);
var manager = new MultiTenancyManager(Substitute.For<IAmbientTenantAccessor>(), new ITenantResolver[0]);
//Act
//Assert
manager.CurrentTenant.ShouldBeNull();
}
@ -25,9 +26,7 @@ namespace Volo.Abp.MultiTenancy
var fakeTenant = new TenantInfo(Guid.NewGuid().ToString(), "acme");
//Act
var manager = new MultiTenancyManager(new[]
var manager = new MultiTenancyManager(Substitute.For<IAmbientTenantAccessor>(), new[]
{
new TenantResolverAction(context =>
{
@ -49,13 +48,11 @@ namespace Volo.Abp.MultiTenancy
var fakeTenant = new TenantInfo(Guid.NewGuid().ToString(), "acme");
//Act
var manager = new MultiTenancyManager(new[]
var manager = new MultiTenancyManager(Substitute.For<IAmbientTenantAccessor>(), new[]
{
new TenantResolverAction(context =>
{
context.Tenant = new TenantInfo(Guid.NewGuid().ToString(), "skipped-tenant");
context.Tenant = new TenantInfo(Guid.NewGuid().ToString(), "skipped-tenant-1");
}),
new TenantResolverAction(context =>
{
@ -64,7 +61,7 @@ namespace Volo.Abp.MultiTenancy
}),
new TenantResolverAction(context =>
{
context.Tenant = new TenantInfo(Guid.NewGuid().ToString(), "skipped-tenant");
context.Tenant = new TenantInfo(Guid.NewGuid().ToString(), "skipped-tenant-2");
context.Handled = true;
})
});
@ -73,5 +70,36 @@ namespace Volo.Abp.MultiTenancy
manager.CurrentTenant.ShouldBe(fakeTenant);
}
[Fact]
public void Should_Get_Ambient_Tenant_If_Changed()
{
//Arrange
var oldTenant = new TenantInfo(Guid.NewGuid().ToString(), "old-tenant");
var manager = new MultiTenancyManager(Substitute.For<IAmbientTenantAccessor>(), new[]
{
new TenantResolverAction(context =>
{
context.Tenant = oldTenant;
context.Handled = true;
})
});
manager.CurrentTenant.ShouldBe(oldTenant);
//Act
var overridedTenant = new TenantInfo(Guid.NewGuid().ToString(), "overrided-tenant");
using (manager.ChangeTenant(overridedTenant))
{
//Assert
manager.CurrentTenant.ShouldBe(overridedTenant);
}
//Assert
manager.CurrentTenant.ShouldBe(oldTenant);
}
}
}

Loading…
Cancel
Save