optimize client assembly download service, add support for site level scripts
This commit is contained in:
parent
98c2f012ee
commit
95ba87945b
@ -531,10 +531,13 @@
|
||||
{
|
||||
foreach (var resource in resources)
|
||||
{
|
||||
if (!resource.Url.Contains("://") && resource.Url.StartsWith("~/"))
|
||||
if (resource.Url.StartsWith("~"))
|
||||
{
|
||||
// create local path
|
||||
resource.Url = resource.Url.Replace("~", alias.BaseUrl + "/" + type + "/" + name);
|
||||
resource.Url = resource.Url.Replace("~", "/" + type + "/" + name + "/").Replace("//", "/");
|
||||
}
|
||||
if (!resource.Url.Contains("://") && alias.BaseUrl != "" && !resource.Url.StartsWith(alias.BaseUrl))
|
||||
{
|
||||
resource.Url = alias.BaseUrl + resource.Url;
|
||||
}
|
||||
|
||||
// ensure resource does not exist already
|
||||
|
@ -33,8 +33,10 @@ namespace Oqtane.Controllers
|
||||
private readonly IHttpContextAccessor _accessor;
|
||||
private readonly IAliasRepository _aliases;
|
||||
private readonly ILogger<InstallationController> _filelogger;
|
||||
private readonly ITenantManager _tenantManager;
|
||||
private readonly ServerStateManager _serverState;
|
||||
|
||||
public InstallationController(IConfigManager configManager, IInstallationManager installationManager, IDatabaseManager databaseManager, ILocalizationManager localizationManager, IMemoryCache cache, IHttpContextAccessor accessor, IAliasRepository aliases, ILogger<InstallationController> filelogger)
|
||||
public InstallationController(IConfigManager configManager, IInstallationManager installationManager, IDatabaseManager databaseManager, ILocalizationManager localizationManager, IMemoryCache cache, IHttpContextAccessor accessor, IAliasRepository aliases, ILogger<InstallationController> filelogger, ITenantManager tenantManager, ServerStateManager serverState)
|
||||
{
|
||||
_configManager = configManager;
|
||||
_installationManager = installationManager;
|
||||
@ -44,6 +46,8 @@ namespace Oqtane.Controllers
|
||||
_accessor = accessor;
|
||||
_aliases = aliases;
|
||||
_filelogger = filelogger;
|
||||
_tenantManager = tenantManager;
|
||||
_serverState = serverState;
|
||||
}
|
||||
|
||||
// POST api/<controller>
|
||||
@ -115,7 +119,9 @@ namespace Oqtane.Controllers
|
||||
|
||||
private List<ClientAssembly> GetAssemblyList()
|
||||
{
|
||||
return _cache.GetOrCreate("assemblieslist", entry =>
|
||||
int siteId = _tenantManager.GetAlias().SiteId;
|
||||
|
||||
return _cache.GetOrCreate($"assemblieslist:{siteId}", entry =>
|
||||
{
|
||||
var binFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
||||
var assemblyList = new List<ClientAssembly>();
|
||||
@ -126,78 +132,43 @@ namespace Oqtane.Controllers
|
||||
{
|
||||
hashfilename = false;
|
||||
}
|
||||
|
||||
// get list of assemblies which should be downloaded to client
|
||||
var assemblies = AppDomain.CurrentDomain.GetOqtaneClientAssemblies();
|
||||
var list = assemblies.Select(a => a.GetName().Name).ToList();
|
||||
|
||||
// populate assemblies
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
// get site assemblies which should be downloaded to client
|
||||
var assemblies = _serverState.GetServerState(siteId).Assemblies;
|
||||
|
||||
// populate assembly list
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
assemblyList.Add(new ClientAssembly(Path.Combine(binFolder, list[i] + ".dll"), hashfilename));
|
||||
if (assembly != Constants.ClientId)
|
||||
{
|
||||
var filepath = Path.Combine(binFolder, assembly) + ".dll";
|
||||
if (System.IO.File.Exists(filepath))
|
||||
{
|
||||
assemblyList.Add(new ClientAssembly(Path.Combine(binFolder, assembly + ".dll"), hashfilename));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// insert satellite assemblies at beginning of list
|
||||
foreach (var culture in _localizationManager.GetInstalledCultures())
|
||||
{
|
||||
var assembliesFolderPath = Path.Combine(binFolder, culture);
|
||||
if (culture == Constants.DefaultCulture)
|
||||
if (culture != Constants.DefaultCulture)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Directory.Exists(assembliesFolderPath))
|
||||
{
|
||||
foreach (var resourceFile in Directory.EnumerateFiles(assembliesFolderPath))
|
||||
var assembliesFolderPath = Path.Combine(binFolder, culture);
|
||||
if (Directory.Exists(assembliesFolderPath))
|
||||
{
|
||||
assemblyList.Insert(0, new ClientAssembly(resourceFile, hashfilename));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_filelogger.LogError(Utilities.LogMessage(this, $"The Satellite Assembly Folder For {culture} Does Not Exist"));
|
||||
}
|
||||
}
|
||||
|
||||
// insert module and theme dependencies at beginning of list
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
foreach (var type in assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(IModule))))
|
||||
{
|
||||
var instance = Activator.CreateInstance(type) as IModule;
|
||||
foreach (string name in instance.ModuleDefinition.Dependencies.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Reverse())
|
||||
{
|
||||
var filepath = Path.Combine(binFolder, name.ToLower().EndsWith(".dll") ? name : name + ".dll");
|
||||
if (System.IO.File.Exists(filepath))
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
if (!assemblyList.Exists(item => item.FilePath == filepath))
|
||||
var filepath = Path.Combine(assembliesFolderPath, assembly) + ".resources.dll";
|
||||
if (System.IO.File.Exists(filepath))
|
||||
{
|
||||
assemblyList.Insert(0, new ClientAssembly(filepath, hashfilename));
|
||||
assemblyList.Insert(0, new ClientAssembly(Path.Combine(assembliesFolderPath, assembly + ".resources.dll"), hashfilename));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_filelogger.LogError(Utilities.LogMessage(this, $"Module {instance.ModuleDefinition.ModuleDefinitionName} Dependency {name}.dll Does Not Exist"));
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (var type in assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(ITheme))))
|
||||
{
|
||||
var instance = Activator.CreateInstance(type) as ITheme;
|
||||
foreach (string name in instance.Theme.Dependencies.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Reverse())
|
||||
else
|
||||
{
|
||||
var filepath = Path.Combine(binFolder, name.ToLower().EndsWith(".dll") ? name : name + ".dll");
|
||||
if (System.IO.File.Exists(filepath))
|
||||
{
|
||||
if (!assemblyList.Exists(item => item.FilePath == filepath))
|
||||
{
|
||||
assemblyList.Insert(0, new ClientAssembly(filepath, hashfilename));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_filelogger.LogError(Utilities.LogMessage(this, $"Theme {instance.Theme.ThemeName} Dependency {name}.dll Does Not Exist"));
|
||||
}
|
||||
_filelogger.LogError(Utilities.LogMessage(this, $"The Satellite Assembly Folder For {culture} Does Not Exist"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -240,21 +211,24 @@ namespace Oqtane.Controllers
|
||||
{
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
if (System.IO.File.Exists(assembly.FilePath))
|
||||
if (Path.GetFileNameWithoutExtension(assembly.FilePath) != Constants.ClientId)
|
||||
{
|
||||
using (var filestream = new FileStream(assembly.FilePath, FileMode.Open, FileAccess.Read))
|
||||
using (var entrystream = archive.CreateEntry(assembly.HashedName).Open())
|
||||
if (System.IO.File.Exists(assembly.FilePath))
|
||||
{
|
||||
filestream.CopyTo(entrystream);
|
||||
using (var filestream = new FileStream(assembly.FilePath, FileMode.Open, FileAccess.Read))
|
||||
using (var entrystream = archive.CreateEntry(assembly.HashedName).Open())
|
||||
{
|
||||
filestream.CopyTo(entrystream);
|
||||
}
|
||||
}
|
||||
}
|
||||
var pdb = assembly.FilePath.Replace(".dll", ".pdb");
|
||||
if (System.IO.File.Exists(pdb))
|
||||
{
|
||||
using (var filestream = new FileStream(pdb, FileMode.Open, FileAccess.Read))
|
||||
using (var entrystream = archive.CreateEntry(assembly.HashedName.Replace(".dll", ".pdb")).Open())
|
||||
var pdb = assembly.FilePath.Replace(".dll", ".pdb");
|
||||
if (System.IO.File.Exists(pdb))
|
||||
{
|
||||
filestream.CopyTo(entrystream);
|
||||
using (var filestream = new FileStream(pdb, FileMode.Open, FileAccess.Read))
|
||||
using (var entrystream = archive.CreateEntry(assembly.HashedName.Replace(".dll", ".pdb")).Open())
|
||||
{
|
||||
filestream.CopyTo(entrystream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
services.AddSingleton<ILoggerProvider, FileLoggerProvider>();
|
||||
services.AddSingleton<AutoValidateAntiforgeryTokenFilter>();
|
||||
services.AddSingleton<IAuthorizationPolicyProvider, AuthorizationPolicyProvider>();
|
||||
services.AddSingleton<ServerStateManager>();
|
||||
return services;
|
||||
}
|
||||
|
||||
|
12
Oqtane.Server/Infrastructure/ServerState.cs
Normal file
12
Oqtane.Server/Infrastructure/ServerState.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Infrastructure
|
||||
{
|
||||
public class ServerState
|
||||
{
|
||||
public int SiteId { get; set; }
|
||||
public List<string> Assemblies { get; set; } = new List<string>();
|
||||
public List<Resource>Scripts { get; set; } = new List<Resource>();
|
||||
}
|
||||
}
|
49
Oqtane.Server/Infrastructure/ServerStateManager.cs
Normal file
49
Oqtane.Server/Infrastructure/ServerStateManager.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Infrastructure
|
||||
{
|
||||
// singleton
|
||||
public class ServerStateManager
|
||||
{
|
||||
private List<ServerState> _serverStates { get; set; }
|
||||
|
||||
public ServerStateManager()
|
||||
{
|
||||
_serverStates = new List<ServerState>();
|
||||
}
|
||||
|
||||
public ServerState GetServerState(int siteId)
|
||||
{
|
||||
var serverState = _serverStates.FirstOrDefault(item => item.SiteId == siteId);
|
||||
if (serverState == null)
|
||||
{
|
||||
serverState = new ServerState();
|
||||
serverState.SiteId = siteId;
|
||||
serverState.Assemblies = new List<string>();
|
||||
serverState.Scripts = new List<Resource>();
|
||||
return serverState;
|
||||
}
|
||||
else
|
||||
{
|
||||
return serverState;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetServerState(int siteId, ServerState serverState)
|
||||
{
|
||||
var serverstate = _serverStates.FirstOrDefault(item => item.SiteId == siteId);
|
||||
if (serverstate == null)
|
||||
{
|
||||
serverState.SiteId = siteId;
|
||||
_serverStates.Add(serverState);
|
||||
}
|
||||
else
|
||||
{
|
||||
serverstate.Assemblies = serverState.Assemblies;
|
||||
serverstate.Scripts = serverState.Scripts;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -36,9 +36,10 @@ namespace Oqtane.Pages
|
||||
private readonly IVisitorRepository _visitors;
|
||||
private readonly IAliasRepository _aliases;
|
||||
private readonly ISettingRepository _settings;
|
||||
private readonly ServerStateManager _serverState;
|
||||
private readonly ILogManager _logger;
|
||||
|
||||
public HostModel(IConfigManager configuration, ITenantManager tenantManager, ILocalizationManager localizationManager, ILanguageRepository languages, IAntiforgery antiforgery, IJwtManager jwtManager, ISiteRepository sites, IPageRepository pages, IUrlMappingRepository urlMappings, IVisitorRepository visitors, IAliasRepository aliases, ISettingRepository settings, ILogManager logger)
|
||||
public HostModel(IConfigManager configuration, ITenantManager tenantManager, ILocalizationManager localizationManager, ILanguageRepository languages, IAntiforgery antiforgery, IJwtManager jwtManager, ISiteRepository sites, IPageRepository pages, IUrlMappingRepository urlMappings, IVisitorRepository visitors, IAliasRepository aliases, ISettingRepository settings, ServerStateManager serverState, ILogManager logger)
|
||||
{
|
||||
_configuration = configuration;
|
||||
_tenantManager = tenantManager;
|
||||
@ -52,6 +53,7 @@ namespace Oqtane.Pages
|
||||
_visitors = visitors;
|
||||
_aliases = aliases;
|
||||
_settings = settings;
|
||||
_serverState = serverState;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@ -117,33 +119,11 @@ namespace Oqtane.Pages
|
||||
{
|
||||
Runtime = site.Runtime;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(site.RenderMode))
|
||||
if (!string.IsNullOrEmpty(site.RenderMode))
|
||||
{
|
||||
RenderMode = site.RenderMode;
|
||||
}
|
||||
if (Runtime == "Server")
|
||||
{
|
||||
ReconnectScript = CreateReconnectScript();
|
||||
}
|
||||
if (site.PwaIsEnabled && site.PwaAppIconFileId != null && site.PwaSplashIconFileId != null)
|
||||
{
|
||||
PWAScript = CreatePWAScript(alias, site, route);
|
||||
}
|
||||
// site level scripts
|
||||
HeadResources += ParseScripts(site.HeadContent);
|
||||
BodyResources += ParseScripts(site.BodyContent);
|
||||
|
||||
// get jwt token for downstream APIs
|
||||
if (User.Identity.IsAuthenticated)
|
||||
{
|
||||
var sitesettings = HttpContext.GetSiteSettings();
|
||||
var secret = sitesettings.GetValue("JwtOptions:Secret", "");
|
||||
if (!string.IsNullOrEmpty(secret))
|
||||
{
|
||||
AuthorizationToken = _jwtManager.GenerateToken(alias, (ClaimsIdentity)User.Identity, secret, sitesettings.GetValue("JwtOptions:Issuer", ""), sitesettings.GetValue("JwtOptions:Audience", ""), int.Parse(sitesettings.GetValue("JwtOptions:Lifetime", "20")));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (site.VisitorTracking)
|
||||
{
|
||||
TrackVisitor(site.SiteId);
|
||||
@ -172,11 +152,33 @@ namespace Oqtane.Pages
|
||||
}
|
||||
}
|
||||
|
||||
// include global resources
|
||||
var assemblies = AppDomain.CurrentDomain.GetOqtaneAssemblies();
|
||||
foreach (Assembly assembly in assemblies)
|
||||
// get jwt token for downstream APIs
|
||||
if (User.Identity.IsAuthenticated)
|
||||
{
|
||||
ProcessHostResources(assembly, alias);
|
||||
var sitesettings = HttpContext.GetSiteSettings();
|
||||
var secret = sitesettings.GetValue("JwtOptions:Secret", "");
|
||||
if (!string.IsNullOrEmpty(secret))
|
||||
{
|
||||
AuthorizationToken = _jwtManager.GenerateToken(alias, (ClaimsIdentity)User.Identity, secret, sitesettings.GetValue("JwtOptions:Issuer", ""), sitesettings.GetValue("JwtOptions:Audience", ""), int.Parse(sitesettings.GetValue("JwtOptions:Lifetime", "20")));
|
||||
}
|
||||
}
|
||||
|
||||
// inject scripts
|
||||
if (Runtime == "Server")
|
||||
{
|
||||
ReconnectScript = CreateReconnectScript();
|
||||
}
|
||||
if (site.PwaIsEnabled && site.PwaAppIconFileId != null && site.PwaSplashIconFileId != null)
|
||||
{
|
||||
PWAScript = CreatePWAScript(alias, site, route);
|
||||
}
|
||||
HeadResources += ParseScripts(site.HeadContent);
|
||||
BodyResources += ParseScripts(site.BodyContent);
|
||||
_sites.InitializeSite(site.SiteId); // populates server state
|
||||
var scripts = _serverState.GetServerState(site.SiteId).Scripts;
|
||||
foreach (var script in scripts)
|
||||
{
|
||||
AddScript(script, alias);
|
||||
}
|
||||
|
||||
// set culture if not specified
|
||||
@ -409,20 +411,6 @@ namespace Oqtane.Pages
|
||||
"</script>";
|
||||
}
|
||||
|
||||
private void ProcessHostResources(Assembly assembly, Alias alias)
|
||||
{
|
||||
var types = assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(IHostResources)));
|
||||
foreach (var type in types)
|
||||
{
|
||||
var obj = Activator.CreateInstance(type) as IHostResources;
|
||||
foreach (var resource in obj.Resources)
|
||||
{
|
||||
resource.Level = ResourceLevel.App;
|
||||
ProcessResource(resource, 0, alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string ParseScripts(string headcontent)
|
||||
{
|
||||
// iterate scripts
|
||||
@ -439,60 +427,39 @@ namespace Oqtane.Pages
|
||||
return scripts;
|
||||
}
|
||||
|
||||
private void ProcessResource(Resource resource, int count, Alias alias)
|
||||
private void AddScript(Resource resource, Alias alias)
|
||||
{
|
||||
var url = (resource.Url.Contains("://")) ? resource.Url : alias.BaseUrl + resource.Url;
|
||||
switch (resource.ResourceType)
|
||||
var script = CreateScript(resource, alias);
|
||||
if (resource.Location == Shared.ResourceLocation.Head)
|
||||
{
|
||||
case ResourceType.Stylesheet:
|
||||
if (!HeadResources.Contains(url, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
string id = "";
|
||||
if (resource.Level == ResourceLevel.Page)
|
||||
{
|
||||
id = "id=\"app-stylesheet-" + resource.Level.ToString().ToLower() + "-" + DateTime.UtcNow.ToString("yyyyMMddHHmmssfff") + "-" + count.ToString("00") + "\" ";
|
||||
}
|
||||
HeadResources += "<link " + id + "rel=\"stylesheet\" href=\"" + url + "\"" + CrossOrigin(resource.CrossOrigin) + Integrity(resource.Integrity) + " type=\"text/css\"/>" + Environment.NewLine;
|
||||
}
|
||||
break;
|
||||
case ResourceType.Script:
|
||||
if (resource.Location == Shared.ResourceLocation.Body)
|
||||
{
|
||||
if (!BodyResources.Contains(url, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
BodyResources += "<script src=\"" + url + "\"" + CrossOrigin(resource.CrossOrigin) + Integrity(resource.Integrity) + "></script>" + Environment.NewLine;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!HeadResources.Contains(resource.Url, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
HeadResources += "<script src=\"" + url + "\"" + CrossOrigin(resource.CrossOrigin) + Integrity(resource.Integrity) + "></script>" + Environment.NewLine;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
private string CrossOrigin(string crossorigin)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(crossorigin))
|
||||
{
|
||||
return " crossorigin=\"" + crossorigin + "\"";
|
||||
if (!HeadResources.Contains(script))
|
||||
{
|
||||
HeadResources += script + Environment.NewLine;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
if (!BodyResources.Contains(script))
|
||||
{
|
||||
BodyResources += script + Environment.NewLine;
|
||||
}
|
||||
}
|
||||
}
|
||||
private string Integrity(string integrity)
|
||||
|
||||
private string CreateScript(Resource resource, Alias alias)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(integrity))
|
||||
if (!string.IsNullOrEmpty(resource.Url))
|
||||
{
|
||||
return " integrity=\"" + integrity + "\"";
|
||||
var url = (resource.Url.Contains("://")) ? resource.Url : alias.BaseUrl + resource.Url;
|
||||
return "<script src=\"" + url + "\"" +
|
||||
((!string.IsNullOrEmpty(resource.CrossOrigin)) ? " crossorigin=\"" + resource.CrossOrigin + "\"" : "") +
|
||||
((!string.IsNullOrEmpty(resource.Integrity)) ? " integrity=\"" + resource.Integrity + "\"" : "") +
|
||||
"></script>";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
// inline script
|
||||
return "<script>" + resource.Content + "</script>";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ namespace Oqtane.Repository
|
||||
Site GetSite(int siteId);
|
||||
Site GetSite(int siteId, bool tracking);
|
||||
void DeleteSite(int siteId);
|
||||
void InitializeSite(int siteId);
|
||||
void CreatePages(Site site, List<PageTemplate> pageTemplates);
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,14 @@ using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Oqtane.Infrastructure;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Modules;
|
||||
using Oqtane.Shared;
|
||||
using Oqtane.Themes;
|
||||
|
||||
namespace Oqtane.Repository
|
||||
{
|
||||
@ -20,15 +22,17 @@ namespace Oqtane.Repository
|
||||
private readonly IPermissionRepository _permissions;
|
||||
private readonly ITenantManager _tenants;
|
||||
private readonly ISettingRepository _settings;
|
||||
private readonly ServerStateManager _serverState;
|
||||
private readonly string settingprefix = "SiteEnabled:";
|
||||
|
||||
public ModuleDefinitionRepository(MasterDBContext context, IMemoryCache cache, IPermissionRepository permissions, ITenantManager tenants, ISettingRepository settings)
|
||||
public ModuleDefinitionRepository(MasterDBContext context, IMemoryCache cache, IPermissionRepository permissions, ITenantManager tenants, ISettingRepository settings, ServerStateManager serverState)
|
||||
{
|
||||
_db = context;
|
||||
_cache = cache;
|
||||
_permissions = permissions;
|
||||
_tenants = tenants;
|
||||
_settings = settings;
|
||||
_serverState = serverState;
|
||||
}
|
||||
|
||||
public IEnumerable<ModuleDefinition> GetModuleDefinitions()
|
||||
@ -182,6 +186,7 @@ namespace Oqtane.Repository
|
||||
var settings = _settings.GetSettings(EntityNames.ModuleDefinition).ToList();
|
||||
|
||||
// populate module definition site settings and permissions
|
||||
var serverState = _serverState.GetServerState(siteId);
|
||||
foreach (ModuleDefinition moduledefinition in ModuleDefinitions)
|
||||
{
|
||||
moduledefinition.SiteId = siteId;
|
||||
@ -196,6 +201,36 @@ namespace Oqtane.Repository
|
||||
moduledefinition.IsEnabled = moduledefinition.IsAutoEnabled;
|
||||
}
|
||||
|
||||
if (moduledefinition.IsEnabled)
|
||||
{
|
||||
// build list of assemblies for site
|
||||
if (!serverState.Assemblies.Contains(moduledefinition.AssemblyName))
|
||||
{
|
||||
serverState.Assemblies.Add(moduledefinition.AssemblyName);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(moduledefinition.Dependencies))
|
||||
{
|
||||
foreach (var assembly in moduledefinition.Dependencies.Replace(".dll", "").Split(',', StringSplitOptions.RemoveEmptyEntries).Reverse())
|
||||
{
|
||||
if (!serverState.Assemblies.Contains(assembly))
|
||||
{
|
||||
serverState.Assemblies.Insert(0, assembly);
|
||||
}
|
||||
}
|
||||
}
|
||||
// build list of scripts for site
|
||||
if (moduledefinition.Resources != null)
|
||||
{
|
||||
foreach (var resource in moduledefinition.Resources.Where(item => item.Level == ResourceLevel.Site))
|
||||
{
|
||||
if (!serverState.Scripts.Contains(resource))
|
||||
{
|
||||
serverState.Scripts.Add(resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (permissions.Count == 0)
|
||||
{
|
||||
// no module definition permissions exist for this site
|
||||
@ -216,6 +251,7 @@ namespace Oqtane.Repository
|
||||
}
|
||||
}
|
||||
}
|
||||
_serverState.SetServerState(siteId, serverState);
|
||||
|
||||
// clean up any orphaned permissions
|
||||
var ids = new HashSet<int>(ModuleDefinitions.Select(item => item.ModuleDefinitionId));
|
||||
@ -295,6 +331,16 @@ namespace Oqtane.Repository
|
||||
moduledefinition.ModuleDefinitionName = qualifiedModuleType;
|
||||
moduledefinition.ControlTypeTemplate = modulecontroltype.Namespace + "." + Constants.ActionToken + ", " + modulecontroltype.Assembly.GetName().Name;
|
||||
moduledefinition.AssemblyName = assembly.GetName().Name;
|
||||
if (moduledefinition.Resources != null)
|
||||
{
|
||||
foreach (var resource in moduledefinition.Resources)
|
||||
{
|
||||
if (resource.Url.StartsWith("~"))
|
||||
{
|
||||
resource.Url = resource.Url.Replace("~", "/Modules/" + Utilities.GetTypeName(moduledefinition.ModuleDefinitionName) + "/").Replace("//", "/");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
moduledefinition.IsPortable = false;
|
||||
if (!string.IsNullOrEmpty(moduledefinition.ServerManagerType))
|
||||
|
@ -24,11 +24,12 @@ namespace Oqtane.Repository
|
||||
private readonly IModuleRepository _moduleRepository;
|
||||
private readonly IPageModuleRepository _pageModuleRepository;
|
||||
private readonly IModuleDefinitionRepository _moduleDefinitionRepository;
|
||||
private readonly IThemeRepository _themeRepository;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IConfigurationRoot _config;
|
||||
|
||||
public SiteRepository(TenantDBContext context, IRoleRepository roleRepository, IProfileRepository profileRepository, IFolderRepository folderRepository, IPageRepository pageRepository,
|
||||
IModuleRepository moduleRepository, IPageModuleRepository pageModuleRepository, IModuleDefinitionRepository moduleDefinitionRepository, IServiceProvider serviceProvider,
|
||||
IModuleRepository moduleRepository, IPageModuleRepository pageModuleRepository, IModuleDefinitionRepository moduleDefinitionRepository, IThemeRepository themeRepository, IServiceProvider serviceProvider,
|
||||
IConfigurationRoot config)
|
||||
{
|
||||
_db = context;
|
||||
@ -39,6 +40,7 @@ namespace Oqtane.Repository
|
||||
_moduleRepository = moduleRepository;
|
||||
_pageModuleRepository = pageModuleRepository;
|
||||
_moduleDefinitionRepository = moduleDefinitionRepository;
|
||||
_themeRepository = themeRepository;
|
||||
_serviceProvider = serviceProvider;
|
||||
_config = config;
|
||||
}
|
||||
@ -88,6 +90,12 @@ namespace Oqtane.Repository
|
||||
_db.SaveChanges();
|
||||
}
|
||||
|
||||
public void InitializeSite(int siteId)
|
||||
{
|
||||
_moduleDefinitionRepository.GetModuleDefinitions(siteId);
|
||||
_themeRepository.GetThemes();
|
||||
}
|
||||
|
||||
private void CreateSite(Site site)
|
||||
{
|
||||
// create default entities for site
|
||||
|
@ -21,14 +21,16 @@ namespace Oqtane.Repository
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly ITenantManager _tenants;
|
||||
private readonly ISettingRepository _settings;
|
||||
private readonly ServerStateManager _serverState;
|
||||
private readonly string settingprefix = "SiteEnabled:";
|
||||
|
||||
public ThemeRepository(MasterDBContext context, IMemoryCache cache, ITenantManager tenants, ISettingRepository settings)
|
||||
public ThemeRepository(MasterDBContext context, IMemoryCache cache, ITenantManager tenants, ISettingRepository settings, ServerStateManager serverState)
|
||||
{
|
||||
_db = context;
|
||||
_cache = cache;
|
||||
_tenants = tenants;
|
||||
_settings = settings;
|
||||
_serverState = serverState;
|
||||
}
|
||||
|
||||
public IEnumerable<Theme> GetThemes()
|
||||
@ -147,6 +149,7 @@ namespace Oqtane.Repository
|
||||
var settings = _settings.GetSettings(EntityNames.Theme).ToList();
|
||||
|
||||
// populate theme site settings
|
||||
var serverState = _serverState.GetServerState(siteId);
|
||||
foreach (Theme theme in Themes)
|
||||
{
|
||||
theme.SiteId = siteId;
|
||||
@ -160,7 +163,38 @@ namespace Oqtane.Repository
|
||||
{
|
||||
theme.IsEnabled = theme.IsAutoEnabled;
|
||||
}
|
||||
|
||||
if (theme.IsEnabled)
|
||||
{
|
||||
// build list of assemblies for site
|
||||
if (!serverState.Assemblies.Contains(theme.AssemblyName))
|
||||
{
|
||||
serverState.Assemblies.Add(theme.AssemblyName);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(theme.Dependencies))
|
||||
{
|
||||
foreach (var assembly in theme.Dependencies.Replace(".dll", "").Split(',', StringSplitOptions.RemoveEmptyEntries).Reverse())
|
||||
{
|
||||
if (!serverState.Assemblies.Contains(assembly))
|
||||
{
|
||||
serverState.Assemblies.Insert(0, assembly);
|
||||
}
|
||||
}
|
||||
}
|
||||
// build list of scripts for site
|
||||
if (theme.Resources != null)
|
||||
{
|
||||
foreach (var resource in theme.Resources.Where(item => item.Level == ResourceLevel.Site))
|
||||
{
|
||||
if (!serverState.Scripts.Contains(resource))
|
||||
{
|
||||
serverState.Scripts.Add(resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_serverState.SetServerState(siteId, serverState);
|
||||
}
|
||||
|
||||
return Themes;
|
||||
@ -225,12 +259,22 @@ namespace Oqtane.Repository
|
||||
Version = new Version(1, 0, 0).ToString()
|
||||
};
|
||||
}
|
||||
|
||||
// set internal properties
|
||||
theme.ThemeName = qualifiedThemeType;
|
||||
theme.Themes = new List<ThemeControl>();
|
||||
theme.Containers = new List<ThemeControl>();
|
||||
theme.AssemblyName = assembly.FullName.Split(",")[0];
|
||||
|
||||
if (theme.Resources != null)
|
||||
{
|
||||
foreach (var resource in theme.Resources)
|
||||
{
|
||||
if (resource.Url.StartsWith("~"))
|
||||
{
|
||||
resource.Url = resource.Url.Replace("~", "/Themes/" + Utilities.GetTypeName(theme.ThemeName) + "/").Replace("//", "/");
|
||||
}
|
||||
}
|
||||
}
|
||||
Debug.WriteLine($"Oqtane Info: Registering Theme {theme.ThemeName}");
|
||||
themes.Add(theme);
|
||||
index = themes.FindIndex(item => item.ThemeName == qualifiedThemeType);
|
||||
|
@ -3,6 +3,7 @@ namespace Oqtane.Shared
|
||||
public enum ResourceLevel
|
||||
{
|
||||
App,
|
||||
Site,
|
||||
Page,
|
||||
Module
|
||||
}
|
||||
|
Reference in New Issue
Block a user