optimizing tenant resolution and routing
This commit is contained in:
@ -464,12 +464,12 @@ namespace Oqtane.Infrastructure
|
||||
{
|
||||
using (var scope = _serviceScopeFactory.CreateScope())
|
||||
{
|
||||
// use the SiteState to set the Alias explicitly so the tenant can be resolved
|
||||
// set the alias explicitly so the tenant can be resolved
|
||||
var aliases = scope.ServiceProvider.GetRequiredService<IAliasRepository>();
|
||||
var firstAlias = install.Aliases.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)[0];
|
||||
var alias = aliases.GetAliases().FirstOrDefault(item => item.Name == firstAlias);
|
||||
var siteState = scope.ServiceProvider.GetRequiredService<SiteState>();
|
||||
siteState.Alias = alias;
|
||||
var tenantManager = scope.ServiceProvider.GetRequiredService<ITenantManager>();
|
||||
tenantManager.SetAlias(alias);
|
||||
|
||||
var sites = scope.ServiceProvider.GetRequiredService<ISiteRepository>();
|
||||
var site = sites.GetSites().FirstOrDefault(item => item.Name == install.SiteName);
|
||||
|
12
Oqtane.Server/Infrastructure/Interfaces/ITenantManager.cs
Normal file
12
Oqtane.Server/Infrastructure/Interfaces/ITenantManager.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Infrastructure
|
||||
{
|
||||
public interface ITenantManager
|
||||
{
|
||||
Alias GetAlias();
|
||||
Tenant GetTenant();
|
||||
void SetAlias(Alias alias);
|
||||
void SetTenant(int tenantId);
|
||||
}
|
||||
}
|
@ -92,11 +92,12 @@ namespace Oqtane.Infrastructure
|
||||
try
|
||||
{
|
||||
var notes = "";
|
||||
var tenants = scope.ServiceProvider.GetRequiredService<ITenantRepository>();
|
||||
var siteState = scope.ServiceProvider.GetRequiredService<SiteState>();
|
||||
foreach (var tenant in tenants.GetTenants())
|
||||
var tenantRepository = scope.ServiceProvider.GetRequiredService<ITenantRepository>();
|
||||
var tenantManager = scope.ServiceProvider.GetRequiredService<ITenantManager>();
|
||||
foreach (var tenant in tenantRepository.GetTenants())
|
||||
{
|
||||
siteState.Alias = new Alias { TenantId = tenant.TenantId };
|
||||
// set tenant and execute job
|
||||
tenantManager.SetTenant(tenant.TenantId);
|
||||
notes += ExecuteJob(scope.ServiceProvider);
|
||||
}
|
||||
log.Notes = notes;
|
||||
|
@ -14,18 +14,18 @@ namespace Oqtane.Infrastructure
|
||||
public class LogManager : ILogManager
|
||||
{
|
||||
private readonly ILogRepository _logs;
|
||||
private readonly ITenantResolver _tenantResolver;
|
||||
private readonly IConfigurationRoot _config;
|
||||
private readonly IUserPermissions _userPermissions;
|
||||
private readonly IHttpContextAccessor _accessor;
|
||||
private readonly Alias _alias;
|
||||
|
||||
public LogManager(ILogRepository logs, ITenantResolver tenantResolver, IConfigurationRoot config, IUserPermissions userPermissions, IHttpContextAccessor accessor)
|
||||
public LogManager(ILogRepository logs, ITenantManager tenantManager, IConfigurationRoot config, IUserPermissions userPermissions, IHttpContextAccessor accessor)
|
||||
{
|
||||
_logs = logs;
|
||||
_tenantResolver = tenantResolver;
|
||||
_config = config;
|
||||
_userPermissions = userPermissions;
|
||||
_accessor = accessor;
|
||||
_alias = tenantManager.GetAlias();
|
||||
}
|
||||
|
||||
public void Log(LogLevel level, object @class, LogFunction function, string message, params object[] args)
|
||||
@ -49,10 +49,9 @@ namespace Oqtane.Infrastructure
|
||||
if (siteId == -1)
|
||||
{
|
||||
log.SiteId = null;
|
||||
Alias alias = _tenantResolver.GetAlias();
|
||||
if (alias != null)
|
||||
if (_alias != null)
|
||||
{
|
||||
log.SiteId = alias.SiteId;
|
||||
log.SiteId = _alias.SiteId;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
41
Oqtane.Server/Infrastructure/Middleware/TenantMiddleware.cs
Normal file
41
Oqtane.Server/Infrastructure/Middleware/TenantMiddleware.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Oqtane.Infrastructure
|
||||
{
|
||||
internal class TenantMiddleware
|
||||
{
|
||||
private readonly RequestDelegate next;
|
||||
|
||||
public TenantMiddleware(RequestDelegate next)
|
||||
{
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
public async Task Invoke(HttpContext context)
|
||||
{
|
||||
// check if framework is installed
|
||||
var config = context.RequestServices.GetService(typeof(IConfiguration)) as IConfiguration;
|
||||
if (!string.IsNullOrEmpty(config.GetConnectionString("DefaultConnection")))
|
||||
{
|
||||
// get alias
|
||||
var tenantManager = context.RequestServices.GetService(typeof(ITenantManager)) as ITenantManager;
|
||||
var alias = tenantManager.GetAlias();
|
||||
|
||||
// rewrite path by removing alias path prefix from api and pages requests
|
||||
if (alias != null && !string.IsNullOrEmpty(alias.Path))
|
||||
{
|
||||
string path = context.Request.Path.ToString();
|
||||
if (path.StartsWith("/" + alias.Path) && (path.Contains("/api/") || path.Contains("/pages/")))
|
||||
{
|
||||
context.Request.Path = path.Replace("/" + alias.Path, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// continue processing
|
||||
if (next != null) await next(context);
|
||||
}
|
||||
}
|
||||
}
|
87
Oqtane.Server/Infrastructure/TenantManager.cs
Normal file
87
Oqtane.Server/Infrastructure/TenantManager.cs
Normal file
@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Repository;
|
||||
using Oqtane.Shared;
|
||||
|
||||
namespace Oqtane.Infrastructure
|
||||
{
|
||||
public class TenantManager : ITenantManager
|
||||
{
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly IAliasRepository _aliasRepository;
|
||||
private readonly ITenantRepository _tenantRepository;
|
||||
private readonly SiteState _siteState;
|
||||
|
||||
public TenantManager(IHttpContextAccessor httpContextAccessor, IAliasRepository aliasRepository, ITenantRepository tenantRepository, SiteState siteState)
|
||||
{
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_aliasRepository = aliasRepository;
|
||||
_tenantRepository = tenantRepository;
|
||||
_siteState = siteState;
|
||||
}
|
||||
|
||||
public Alias GetAlias()
|
||||
{
|
||||
Alias alias = null;
|
||||
|
||||
if (_siteState != null && _siteState.Alias != null)
|
||||
{
|
||||
alias = _siteState.Alias;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if there is http context
|
||||
if (_httpContextAccessor.HttpContext != null)
|
||||
{
|
||||
// legacy support for client api requests which would include the alias as a path prefix ( ie. {alias}/api/[controller] )
|
||||
int aliasId;
|
||||
string[] segments = _httpContextAccessor.HttpContext.Request.Path.Value.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (segments.Length > 1 && (segments[1] == "api" || segments[1] == "pages") && int.TryParse(segments[0], out aliasId))
|
||||
{
|
||||
alias = _aliasRepository.GetAliases().ToList().FirstOrDefault(item => item.AliasId == aliasId);
|
||||
}
|
||||
|
||||
// resolve alias based on host name and path
|
||||
if (alias == null)
|
||||
{
|
||||
string name = _httpContextAccessor.HttpContext.Request.Host.Value + _httpContextAccessor.HttpContext.Request.Path;
|
||||
alias = _aliasRepository.GetAlias(name);
|
||||
}
|
||||
|
||||
// if there is a match save it
|
||||
if (alias != null)
|
||||
{
|
||||
_siteState.Alias = alias;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return alias;
|
||||
}
|
||||
|
||||
public Tenant GetTenant()
|
||||
{
|
||||
var alias = GetAlias();
|
||||
if (alias != null)
|
||||
{
|
||||
// return tenant details
|
||||
return _tenantRepository.GetTenants().ToList().FirstOrDefault(item => item.TenantId == alias.TenantId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SetAlias(Alias alias)
|
||||
{
|
||||
// background processes can set the alias using the SiteState service
|
||||
_siteState.Alias = alias;
|
||||
}
|
||||
|
||||
public void SetTenant(int tenantId)
|
||||
{
|
||||
// background processes can set the alias using the SiteState service
|
||||
_siteState.Alias = new Alias { TenantId = tenantId };
|
||||
}
|
||||
}
|
||||
}
|
@ -27,9 +27,9 @@ namespace Oqtane.Infrastructure
|
||||
// core framework upgrade logic - executed for every tenant
|
||||
using (var scope = _serviceScopeFactory.CreateScope())
|
||||
{
|
||||
// set SiteState based on tenant
|
||||
var siteState = scope.ServiceProvider.GetRequiredService<SiteState>();
|
||||
siteState.Alias = new Alias { TenantId = tenant.TenantId };
|
||||
// set tenant
|
||||
var tenantManager = scope.ServiceProvider.GetRequiredService<ITenantManager>();
|
||||
tenantManager.SetTenant(tenant.TenantId);
|
||||
|
||||
switch (version)
|
||||
{
|
||||
|
Reference in New Issue
Block a user