Performance improvements, refactoring of multi-tenant support, split Alias and Tenant entities for cleaner separation of concerns, create an additional site during installation for demonstratng multitenancy
This commit is contained in:
91
Oqtane.Server/Repository/AliasRepository.cs
Normal file
91
Oqtane.Server/Repository/AliasRepository.cs
Normal file
@ -0,0 +1,91 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Oqtane.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using System;
|
||||
|
||||
namespace Oqtane.Repository
|
||||
{
|
||||
public class AliasRepository : IAliasRepository
|
||||
{
|
||||
private HostContext db;
|
||||
private readonly IMemoryCache _cache;
|
||||
|
||||
public AliasRepository(HostContext context, IMemoryCache cache)
|
||||
{
|
||||
db = context;
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
public IEnumerable<Alias> GetAliases()
|
||||
{
|
||||
try
|
||||
{
|
||||
IEnumerable<Alias> aliases = _cache.GetOrCreate("aliases", entry =>
|
||||
{
|
||||
entry.SlidingExpiration = TimeSpan.FromMinutes(30);
|
||||
return db.Alias.ToList();
|
||||
});
|
||||
return aliases;
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddAlias(Alias alias)
|
||||
{
|
||||
try
|
||||
{
|
||||
db.Alias.Add(alias);
|
||||
db.SaveChanges();
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateAlias(Alias alias)
|
||||
{
|
||||
try
|
||||
{
|
||||
db.Entry(alias).State = EntityState.Modified;
|
||||
db.SaveChanges();
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public Alias GetAlias(int aliasId)
|
||||
{
|
||||
try
|
||||
{
|
||||
Alias alias = db.Alias.Find(aliasId);
|
||||
return alias;
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteAlias(int aliasId)
|
||||
{
|
||||
try
|
||||
{
|
||||
Alias alias = db.Alias.Find(aliasId);
|
||||
db.Alias.Remove(alias);
|
||||
db.SaveChanges();
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -8,9 +8,9 @@ namespace Oqtane.Repository
|
||||
{
|
||||
private Tenant tenant;
|
||||
|
||||
public ContextBase(ITenantRepository TenantRepository)
|
||||
public ContextBase(ITenantResolver TenantResolver)
|
||||
{
|
||||
tenant = TenantRepository.GetTenant();
|
||||
tenant = TenantResolver.GetTenant();
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
|
@ -7,6 +7,7 @@ namespace Oqtane.Repository
|
||||
{
|
||||
public HostContext(DbContextOptions<HostContext> options) : base(options) { }
|
||||
|
||||
public virtual DbSet<Alias> Alias { get; set; }
|
||||
public virtual DbSet<Tenant> Tenant { get; set; }
|
||||
}
|
||||
}
|
||||
|
14
Oqtane.Server/Repository/IAliasRepository.cs
Normal file
14
Oqtane.Server/Repository/IAliasRepository.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Repository
|
||||
{
|
||||
public interface IAliasRepository
|
||||
{
|
||||
IEnumerable<Alias> GetAliases();
|
||||
void AddAlias(Alias alias);
|
||||
void UpdateAlias(Alias alias);
|
||||
Alias GetAlias(int aliasId);
|
||||
void DeleteAlias(int aliasId);
|
||||
}
|
||||
}
|
@ -1,9 +1,14 @@
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Oqtane.Repository
|
||||
{
|
||||
public interface ITenantRepository
|
||||
{
|
||||
Tenant GetTenant();
|
||||
IEnumerable<Tenant> GetTenants();
|
||||
void AddTenant(Tenant tenant);
|
||||
void UpdateTenant(Tenant tenant);
|
||||
Tenant GetTenant(int tenantId);
|
||||
void DeleteTenant(int tenantId);
|
||||
}
|
||||
}
|
||||
|
9
Oqtane.Server/Repository/ITenantResolver.cs
Normal file
9
Oqtane.Server/Repository/ITenantResolver.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Repository
|
||||
{
|
||||
public interface ITenantResolver
|
||||
{
|
||||
Tenant GetTenant();
|
||||
}
|
||||
}
|
@ -14,9 +14,9 @@ namespace Oqtane.Repository
|
||||
|
||||
private readonly Tenant tenant;
|
||||
|
||||
public TenantContext(ITenantRepository TenantRepository)
|
||||
public TenantContext(ITenantResolver TenantResolver)
|
||||
{
|
||||
tenant = TenantRepository.GetTenant();
|
||||
tenant = TenantResolver.GetTenant();
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
|
@ -4,6 +4,7 @@ using System.Linq;
|
||||
using Oqtane.Models;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Oqtane.Repository
|
||||
{
|
||||
@ -11,23 +12,14 @@ namespace Oqtane.Repository
|
||||
{
|
||||
private HostContext db;
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly string alias;
|
||||
|
||||
public TenantRepository(HostContext context, IMemoryCache cache, IHttpContextAccessor accessor)
|
||||
public TenantRepository(HostContext context, IMemoryCache cache)
|
||||
{
|
||||
db = context;
|
||||
_cache = cache;
|
||||
|
||||
// get site alias based on request context
|
||||
alias = accessor.HttpContext.Request.Host.Value;
|
||||
string path = accessor.HttpContext.Request.Path.Value;
|
||||
if (path.StartsWith("/~") && !path.StartsWith("/~/"))
|
||||
{
|
||||
alias += path.Substring(0, path.IndexOf("/", 1));
|
||||
}
|
||||
}
|
||||
|
||||
public Tenant GetTenant()
|
||||
public IEnumerable<Tenant> GetTenants()
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -36,15 +28,45 @@ namespace Oqtane.Repository
|
||||
entry.SlidingExpiration = TimeSpan.FromMinutes(30);
|
||||
return db.Tenant.ToList();
|
||||
});
|
||||
Tenant tenant;
|
||||
if (tenants.Count() == 1)
|
||||
{
|
||||
tenant = tenants.FirstOrDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
tenant = tenants.Where(item => item.Alias == alias).FirstOrDefault();
|
||||
}
|
||||
return tenants;
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddTenant(Tenant tenant)
|
||||
{
|
||||
try
|
||||
{
|
||||
db.Tenant.Add(tenant);
|
||||
db.SaveChanges();
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateTenant(Tenant tenant)
|
||||
{
|
||||
try
|
||||
{
|
||||
db.Entry(tenant).State = EntityState.Modified;
|
||||
db.SaveChanges();
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public Tenant GetTenant(int tenantId)
|
||||
{
|
||||
try
|
||||
{
|
||||
Tenant tenant = db.Tenant.Find(tenantId);
|
||||
return tenant;
|
||||
}
|
||||
catch
|
||||
@ -52,5 +74,19 @@ namespace Oqtane.Repository
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteTenant(int tenantId)
|
||||
{
|
||||
try
|
||||
{
|
||||
Tenant tenant = db.Tenant.Find(tenantId);
|
||||
db.Tenant.Remove(tenant);
|
||||
db.SaveChanges();
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
48
Oqtane.Server/Repository/TenantResolver.cs
Normal file
48
Oqtane.Server/Repository/TenantResolver.cs
Normal file
@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Oqtane.Models;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace Oqtane.Repository
|
||||
{
|
||||
public class TenantResolver : ITenantResolver
|
||||
{
|
||||
private HostContext db;
|
||||
private readonly string aliasname;
|
||||
private readonly IAliasRepository _aliasrepository;
|
||||
private readonly ITenantRepository _tenantrepository;
|
||||
|
||||
public TenantResolver(HostContext context, IHttpContextAccessor accessor, IAliasRepository aliasrepository, ITenantRepository tenantrepository)
|
||||
{
|
||||
db = context;
|
||||
_aliasrepository = aliasrepository;
|
||||
_tenantrepository = tenantrepository;
|
||||
|
||||
// get alias based on request context
|
||||
aliasname = accessor.HttpContext.Request.Host.Value;
|
||||
string path = accessor.HttpContext.Request.Path.Value;
|
||||
string[] segments = path.Split('/');
|
||||
if (segments[1] != "~")
|
||||
{
|
||||
aliasname += "/" + segments[1];
|
||||
}
|
||||
}
|
||||
|
||||
public Tenant GetTenant()
|
||||
{
|
||||
try
|
||||
{
|
||||
IEnumerable<Alias> aliases = _aliasrepository.GetAliases(); // cached
|
||||
Alias alias = aliases.Where(item => item.Name == aliasname).FirstOrDefault();
|
||||
IEnumerable<Tenant> tenants = _tenantrepository.GetTenants(); // cached
|
||||
return tenants.Where(item => item.TenantId == alias.TenantId).FirstOrDefault();
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user