Browse Source

Introduce ITenantResolveResultAccessor.

pull/926/head
Halil ibrahim Kalkan 8 years ago
parent
commit
25bf043c8e
  1. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/CookieTenantResolveContributor.cs
  2. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/DomainTenantResolveContributor.cs
  3. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HeaderTenantResolveContributor.cs
  4. 40
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpContextTenantResolveResultAccessor.cs
  5. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpTenantResolveContributerBase.cs
  6. 9
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/ITenantResolveResultAccessor.cs
  7. 35
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs
  8. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/QueryStringTenantResolveContributor.cs
  9. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/RouteTenantResolveContributor.cs
  10. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en.json
  11. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/tr.json
  12. 8
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ActionTenantResolveContributor.cs
  13. 4
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AsyncLocalCurrentTenantAccessor.cs
  14. 8
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentClaimsPrincipalTenantResolveContributor.cs
  15. 16
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentTenant.cs
  16. 12
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ICurrentTenantAccessor.cs
  17. 13
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ICurrentTenantIdAccessor.cs
  18. 2
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantResolveContributor.cs
  19. 4
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantResolver.cs
  20. 10
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveContributorBase.cs
  21. 16
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveResult.cs
  22. 18
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolver.cs

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];

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

@ -9,6 +9,10 @@ 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 static readonly string[] ProtocolPrefixes = { "http://", "https://" };
private readonly string _domainFormat; private readonly string _domainFormat;

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; }
}
}

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

@ -12,43 +12,44 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
private readonly ITenantResolver _tenantResolver; private readonly ITenantResolver _tenantResolver;
private readonly ITenantStore _tenantStore; private readonly ITenantStore _tenantStore;
private readonly ICurrentTenant _currentTenant; private readonly ICurrentTenant _currentTenant;
private readonly ITenantResolveResultAccessor _tenantResolveResultAccessor;
public MultiTenancyMiddleware( public MultiTenancyMiddleware(
RequestDelegate next, RequestDelegate next,
ITenantResolver tenantResolver, ITenantResolver tenantResolver,
ITenantStore tenantStore, ITenantStore tenantStore,
ICurrentTenant currentTenant) ICurrentTenant currentTenant,
ITenantResolveResultAccessor tenantResolveResultAccessor)
{ {
_next = next; _next = next;
_tenantResolver = tenantResolver; _tenantResolver = tenantResolver;
_tenantStore = tenantStore; _tenantStore = tenantStore;
_currentTenant = currentTenant; _currentTenant = currentTenant;
_tenantResolveResultAccessor = tenantResolveResultAccessor;
} }
public async Task Invoke(HttpContext httpContext) public async Task Invoke(HttpContext httpContext)
{ {
var tenant = await ResolveCurrentTenantAsync(); var resolveResult = _tenantResolver.ResolveTenantIdOrName();
using (_currentTenant.Change(tenant?.Id, tenant?.Name)) _tenantResolveResultAccessor.Result = resolveResult;
{
await _next(httpContext);
}
}
private async Task<TenantConfiguration> 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<TenantConfiguration> FindTenantAsync(string tenantIdOrName) private async Task<TenantConfiguration> FindTenantAsync(string tenantIdOrName)

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.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en.json

@ -3,9 +3,9 @@
"texts": { "texts": {
"GivenTenantIsNotAvailable": "Given tenant is not available: {0}", "GivenTenantIsNotAvailable": "Given tenant is not available: {0}",
"Tenant": "Tenant", "Tenant": "Tenant",
"Switch": "Switch", "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": "Seçili değil" "NotSelected": "Not selected"
} }
} }

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

@ -3,9 +3,9 @@
"texts": { "texts": {
"GivenTenantIsNotAvailable": "İstenilen müşteri bulunamadı: {0}", "GivenTenantIsNotAvailable": "İstenilen müşteri bulunamadı: {0}",
"Tenant": "Müşteri", "Tenant": "Müşteri",
"Switch": "Değiştir", "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": "Not selected" "NotSelected": "Seçili değil"
} }
} }

8
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);
} }

4
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AsyncLocalCurrentTenantIdAccessor.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AsyncLocalCurrentTenantAccessor.cs

@ -3,7 +3,7 @@ using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MultiTenancy namespace Volo.Abp.MultiTenancy
{ {
public class AsyncLocalCurrentTenantIdAccessor : ICurrentTenantIdAccessor, ISingletonDependency public class AsyncLocalCurrentTenantAccessor : ICurrentTenantAccessor, ISingletonDependency
{ {
public BasicTenantInfo Current public BasicTenantInfo Current
{ {
@ -13,7 +13,7 @@ namespace Volo.Abp.MultiTenancy
private readonly AsyncLocal<BasicTenantInfo> _currentScope; private readonly AsyncLocal<BasicTenantInfo> _currentScope;
public AsyncLocalCurrentTenantIdAccessor() public AsyncLocalCurrentTenantAccessor()
{ {
_currentScope = new AsyncLocal<BasicTenantInfo>(); _currentScope = new AsyncLocal<BasicTenantInfo>();
} }

8
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)

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

@ -7,15 +7,15 @@ namespace Volo.Abp.MultiTenancy
{ {
public virtual bool IsAvailable => Id.HasValue; public virtual bool IsAvailable => Id.HasValue;
public virtual Guid? Id => _currentTenantIdAccessor.Current?.TenantId; public virtual Guid? Id => _currentTenantAccessor.Current?.TenantId;
public string Name => _currentTenantIdAccessor.Current?.Name; public string Name => _currentTenantAccessor.Current?.Name;
private readonly ICurrentTenantIdAccessor _currentTenantIdAccessor; private readonly ICurrentTenantAccessor _currentTenantAccessor;
public CurrentTenant(ICurrentTenantIdAccessor currentTenantIdAccessor) public CurrentTenant(ICurrentTenantAccessor currentTenantAccessor)
{ {
_currentTenantIdAccessor = currentTenantIdAccessor; _currentTenantAccessor = currentTenantAccessor;
} }
public IDisposable Change(Guid? id, string name = null) public IDisposable Change(Guid? id, string name = null)
@ -25,11 +25,11 @@ namespace Volo.Abp.MultiTenancy
private IDisposable SetCurrent(Guid? tenantId, string name = null) private IDisposable SetCurrent(Guid? tenantId, string name = null)
{ {
var parentScope = _currentTenantIdAccessor.Current; var parentScope = _currentTenantAccessor.Current;
_currentTenantIdAccessor.Current = new BasicTenantInfo(tenantId, name); _currentTenantAccessor.Current = new BasicTenantInfo(tenantId, name);
return new DisposeAction(() => return new DisposeAction(() =>
{ {
_currentTenantIdAccessor.Current = parentScope; _currentTenantAccessor.Current = parentScope;
}); });
} }
} }

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; }
}
}

13
framework/src/Volo.Abp.MultiTenancy/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
{
BasicTenantInfo Current { get; set; }
}
}

2
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/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();
} }
} }

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);
}
}

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/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;
} }
} }
} }
Loading…
Cancel
Save