fix #5005 - adds versioning (ie. fingerprinting) for static assets - core, modules, and themes.
This commit is contained in:
parent
7a9c637e03
commit
153a689bdb
|
@ -391,7 +391,7 @@
|
|||
if (themetype != null)
|
||||
{
|
||||
// get resources for theme (ITheme)
|
||||
page.Resources = ManagePageResources(page.Resources, theme.Resources, ResourceLevel.Page, alias, "Themes", Utilities.GetTypeName(theme.ThemeName));
|
||||
page.Resources = ManagePageResources(page.Resources, theme.Resources, ResourceLevel.Page, alias, "Themes", Utilities.GetTypeName(theme.ThemeName), theme.Hash);
|
||||
|
||||
var themeobject = Activator.CreateInstance(themetype) as IThemeControl;
|
||||
if (themeobject != null)
|
||||
|
@ -401,7 +401,7 @@
|
|||
panes = themeobject.Panes;
|
||||
}
|
||||
// get resources for theme control
|
||||
page.Resources = ManagePageResources(page.Resources, themeobject.Resources, ResourceLevel.Page, alias, "Themes", themetype.Namespace);
|
||||
page.Resources = ManagePageResources(page.Resources, themeobject.Resources, ResourceLevel.Page, alias, "Themes", themetype.Namespace, theme.Hash);
|
||||
}
|
||||
}
|
||||
// theme settings components are dynamically loaded within the framework Page Management module
|
||||
|
@ -411,7 +411,7 @@
|
|||
if (settingsType != null)
|
||||
{
|
||||
var objSettings = Activator.CreateInstance(settingsType) as IModuleControl;
|
||||
page.Resources = ManagePageResources(page.Resources, objSettings.Resources, ResourceLevel.Module, alias, "Modules", settingsType.Namespace);
|
||||
page.Resources = ManagePageResources(page.Resources, objSettings.Resources, ResourceLevel.Module, alias, "Modules", settingsType.Namespace, theme.Hash);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -455,7 +455,7 @@
|
|||
|
||||
if (module.ModuleDefinition != null && (module.ModuleDefinition.Runtimes == "" || module.ModuleDefinition.Runtimes.Contains(Runtime)))
|
||||
{
|
||||
page.Resources = ManagePageResources(page.Resources, module.ModuleDefinition.Resources, ResourceLevel.Module, alias, "Modules", Utilities.GetTypeName(module.ModuleDefinition.ModuleDefinitionName));
|
||||
page.Resources = ManagePageResources(page.Resources, module.ModuleDefinition.Resources, ResourceLevel.Module, alias, "Modules", Utilities.GetTypeName(module.ModuleDefinition.ModuleDefinitionName), module.ModuleDefinition.Hash);
|
||||
|
||||
// handle default action
|
||||
if (action == Constants.DefaultAction && !string.IsNullOrEmpty(module.ModuleDefinition.DefaultAction))
|
||||
|
@ -504,7 +504,7 @@
|
|||
module.RenderMode = moduleobject.RenderMode;
|
||||
module.Prerender = moduleobject.Prerender;
|
||||
|
||||
page.Resources = ManagePageResources(page.Resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace);
|
||||
page.Resources = ManagePageResources(page.Resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace, module.ModuleDefinition?.Hash);
|
||||
|
||||
// settings components are dynamically loaded within the framework Settings module
|
||||
if (action.ToLower() == "settings" && module.ModuleDefinition != null)
|
||||
|
@ -525,7 +525,7 @@
|
|||
if (moduletype != null)
|
||||
{
|
||||
moduleobject = Activator.CreateInstance(moduletype) as IModuleControl;
|
||||
page.Resources = ManagePageResources(page.Resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace);
|
||||
page.Resources = ManagePageResources(page.Resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace, module.ModuleDefinition?.Hash);
|
||||
}
|
||||
|
||||
// container settings component
|
||||
|
@ -536,7 +536,7 @@
|
|||
if (moduletype != null)
|
||||
{
|
||||
moduleobject = Activator.CreateInstance(moduletype) as IModuleControl;
|
||||
page.Resources = ManagePageResources(page.Resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace);
|
||||
page.Resources = ManagePageResources(page.Resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace, theme.Hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -595,7 +595,7 @@
|
|||
return (page, modules);
|
||||
}
|
||||
|
||||
private List<Resource> ManagePageResources(List<Resource> pageresources, List<Resource> resources, ResourceLevel level, Alias alias, string type, string name)
|
||||
private List<Resource> ManagePageResources(List<Resource> pageresources, List<Resource> resources, ResourceLevel level, Alias alias, string type, string name, string version)
|
||||
{
|
||||
if (resources != null)
|
||||
{
|
||||
|
@ -615,7 +615,7 @@
|
|||
// ensure resource does not exist already
|
||||
if (!pageresources.Exists(item => item.Url.ToLower() == resource.Url.ToLower()))
|
||||
{
|
||||
pageresources.Add(resource.Clone(level, name));
|
||||
pageresources.Add(resource.Clone(level, name, version));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<base href="/" />
|
||||
<link rel="stylesheet" href="css/app.css" />
|
||||
<link rel="stylesheet" href="css/app.css?v=@_hash" />
|
||||
@if (_scripts.Contains("PWA Manifest"))
|
||||
{
|
||||
<link id="app-manifest" rel="manifest" />
|
||||
|
@ -70,15 +70,15 @@
|
|||
}
|
||||
|
||||
<script src="_framework/blazor.web.js"></script>
|
||||
<script src="js/app.js"></script>
|
||||
<script src="js/loadjs.min.js"></script>
|
||||
<script src="js/interop.js"></script>
|
||||
<script src="js/app.js?v=@_hash"></script>
|
||||
<script src="js/loadjs.min.js?v=@_hash"></script>
|
||||
<script src="js/interop.js?v=@_hash"></script>
|
||||
|
||||
@((MarkupString)_scripts)
|
||||
@((MarkupString)_bodyResources)
|
||||
@if (_renderMode == RenderModes.Static)
|
||||
{
|
||||
<page-script src="./js/reload.js"></page-script>
|
||||
<page-script src="./js/reload.js?v=@_hash"></page-script>
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -94,6 +94,7 @@
|
|||
private string _renderMode = RenderModes.Interactive;
|
||||
private string _runtime = Runtimes.Server;
|
||||
private bool _prerender = true;
|
||||
private string _hash = "";
|
||||
private int _visitorId = -1;
|
||||
private string _antiForgeryToken = "";
|
||||
private string _remoteIPAddress = "";
|
||||
|
@ -136,6 +137,8 @@
|
|||
_renderMode = site.RenderMode;
|
||||
_runtime = site.Runtime;
|
||||
_prerender = site.Prerender;
|
||||
_hash = site.Hash;
|
||||
|
||||
var modules = new List<Module>();
|
||||
|
||||
Route route = new Route(url, alias.Path);
|
||||
|
@ -605,13 +608,13 @@
|
|||
var theme = site.Themes.FirstOrDefault(item => item.Themes.Any(item => item.TypeName == themeType));
|
||||
if (theme != null)
|
||||
{
|
||||
resources = AddResources(resources, theme.Resources, ResourceLevel.Page, alias, "Themes", Utilities.GetTypeName(theme.ThemeName), site.RenderMode);
|
||||
resources = AddResources(resources, theme.Resources, ResourceLevel.Page, alias, "Themes", Utilities.GetTypeName(theme.ThemeName), theme.Hash, site.RenderMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
// fallback to default Oqtane theme
|
||||
theme = site.Themes.FirstOrDefault(item => item.Themes.Any(item => item.TypeName == Constants.DefaultTheme));
|
||||
resources = AddResources(resources, theme.Resources, ResourceLevel.Page, alias, "Themes", Utilities.GetTypeName(theme.ThemeName), site.RenderMode);
|
||||
resources = AddResources(resources, theme.Resources, ResourceLevel.Page, alias, "Themes", Utilities.GetTypeName(theme.ThemeName), theme.Hash, site.RenderMode);
|
||||
}
|
||||
var type = Type.GetType(themeType);
|
||||
if (type != null)
|
||||
|
@ -619,7 +622,7 @@
|
|||
var obj = Activator.CreateInstance(type) as IThemeControl;
|
||||
if (obj != null)
|
||||
{
|
||||
resources = AddResources(resources, obj.Resources, ResourceLevel.Page, alias, "Themes", type.Namespace, site.RenderMode);
|
||||
resources = AddResources(resources, obj.Resources, ResourceLevel.Page, alias, "Themes", type.Namespace, theme.Hash, site.RenderMode);
|
||||
}
|
||||
}
|
||||
// theme settings components are dynamically loaded within the framework Page Management module
|
||||
|
@ -629,7 +632,7 @@
|
|||
if (settingsType != null)
|
||||
{
|
||||
var objSettings = Activator.CreateInstance(settingsType) as IModuleControl;
|
||||
resources = AddResources(resources, objSettings.Resources, ResourceLevel.Module, alias, "Modules", settingsType.Namespace, site.RenderMode);
|
||||
resources = AddResources(resources, objSettings.Resources, ResourceLevel.Module, alias, "Modules", settingsType.Namespace, theme.Hash, site.RenderMode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -638,7 +641,7 @@
|
|||
var typename = "";
|
||||
if (module.ModuleDefinition != null)
|
||||
{
|
||||
resources = AddResources(resources, module.ModuleDefinition.Resources, ResourceLevel.Module, alias, "Modules", Utilities.GetTypeName(module.ModuleDefinition.ModuleDefinitionName), site.RenderMode);
|
||||
resources = AddResources(resources, module.ModuleDefinition.Resources, ResourceLevel.Module, alias, "Modules", Utilities.GetTypeName(module.ModuleDefinition.ModuleDefinitionName), module.ModuleDefinition.Hash, site.RenderMode);
|
||||
|
||||
// handle default action
|
||||
if (action == Constants.DefaultAction && !string.IsNullOrEmpty(module.ModuleDefinition.DefaultAction))
|
||||
|
@ -684,7 +687,7 @@
|
|||
var moduleobject = Activator.CreateInstance(moduletype) as IModuleControl;
|
||||
if (moduleobject != null)
|
||||
{
|
||||
resources = AddResources(resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace, site.RenderMode);
|
||||
resources = AddResources(resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace, module.ModuleDefinition?.Hash, site.RenderMode);
|
||||
|
||||
// settings components are dynamically loaded within the framework Settings module
|
||||
if (action.ToLower() == "settings" && module.ModuleDefinition != null)
|
||||
|
@ -705,7 +708,7 @@
|
|||
if (moduletype != null)
|
||||
{
|
||||
moduleobject = Activator.CreateInstance(moduletype) as IModuleControl;
|
||||
resources = AddResources(resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace, site.RenderMode);
|
||||
resources = AddResources(resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace, module.ModuleDefinition?.Hash, site.RenderMode);
|
||||
}
|
||||
|
||||
// container settings component
|
||||
|
@ -715,7 +718,7 @@
|
|||
if (moduletype != null)
|
||||
{
|
||||
moduleobject = Activator.CreateInstance(moduletype) as IModuleControl;
|
||||
resources = AddResources(resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace, site.RenderMode);
|
||||
resources = AddResources(resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace, theme.Hash, site.RenderMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -731,7 +734,7 @@
|
|||
{
|
||||
if (module.ModuleDefinition?.Resources != null)
|
||||
{
|
||||
resources = AddResources(resources, module.ModuleDefinition.Resources.Where(item => item.ResourceType == ResourceType.Script && item.Level == ResourceLevel.Site).ToList(), ResourceLevel.Module, alias, "Modules", Utilities.GetTypeName(module.ModuleDefinition.ModuleDefinitionName), site.RenderMode);
|
||||
resources = AddResources(resources, module.ModuleDefinition.Resources.Where(item => item.ResourceType == ResourceType.Script && item.Level == ResourceLevel.Site).ToList(), ResourceLevel.Module, alias, "Modules", Utilities.GetTypeName(module.ModuleDefinition.ModuleDefinitionName), module.ModuleDefinition.Hash, site.RenderMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -739,7 +742,7 @@
|
|||
return resources;
|
||||
}
|
||||
|
||||
private List<Resource> AddResources(List<Resource> pageresources, List<Resource> resources, ResourceLevel level, Alias alias, string type, string name, string rendermode)
|
||||
private List<Resource> AddResources(List<Resource> pageresources, List<Resource> resources, ResourceLevel level, Alias alias, string type, string name, string version, string rendermode)
|
||||
{
|
||||
if (resources != null)
|
||||
{
|
||||
|
@ -759,7 +762,7 @@
|
|||
// ensure resource does not exist already
|
||||
if (!pageresources.Exists(item => item.Url.ToLower() == resource.Url.ToLower()))
|
||||
{
|
||||
pageresources.Add(resource.Clone(level, name));
|
||||
pageresources.Add(resource.Clone(level, name, version));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -286,7 +286,7 @@ namespace Oqtane.Controllers
|
|||
DateTime lastwritetime = System.IO.File.GetLastWriteTime(filepath);
|
||||
if (hashfilename)
|
||||
{
|
||||
HashedName = GetDeterministicHashCode(filepath).ToString("X8") + "." + lastwritetime.ToString("yyyyMMddHHmmss") + Path.GetExtension(filepath);
|
||||
HashedName = Utilities.GenerateSimpleHash(filepath) + "." + lastwritetime.ToString("yyyyMMddHHmmss") + Path.GetExtension(filepath);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -297,25 +297,5 @@ namespace Oqtane.Controllers
|
|||
public string FilePath { get; private set; }
|
||||
public string HashedName { get; private set; }
|
||||
}
|
||||
|
||||
private static int GetDeterministicHashCode(string value)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash1 = (5381 << 16) + 5381;
|
||||
int hash2 = hash1;
|
||||
|
||||
for (int i = 0; i < value.Length; i += 2)
|
||||
{
|
||||
hash1 = ((hash1 << 5) + hash1) ^ value[i];
|
||||
if (i == value.Length - 1)
|
||||
break;
|
||||
hash2 = ((hash2 << 5) + hash2) ^ value[i + 1];
|
||||
}
|
||||
|
||||
return hash1 + (hash2 * 1566083941);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ namespace Oqtane.Controllers
|
|||
if (user != null)
|
||||
{
|
||||
email = user.Email;
|
||||
_configManager.AddOrUpdateSetting("PackageRegistryEmail", email, false);
|
||||
_configManager.AddOrUpdateSetting("PackageRegistryEmail", email, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -175,6 +175,12 @@ namespace Oqtane.Infrastructure
|
|||
installationid = Guid.NewGuid().ToString();
|
||||
AddOrUpdateSetting("InstallationId", installationid, true);
|
||||
}
|
||||
var version = GetSetting("InstallationVersion", "");
|
||||
if (version != Constants.Version)
|
||||
{
|
||||
AddOrUpdateSetting("InstallationVersion", Constants.Version, true);
|
||||
AddOrUpdateSetting("InstallationDate", DateTime.UtcNow.ToString("yyyyMMddHHmm"), true);
|
||||
}
|
||||
return installationid;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -265,6 +265,7 @@ namespace Oqtane.Infrastructure
|
|||
var installation = IsInstalled();
|
||||
try
|
||||
{
|
||||
UpdateInstallation();
|
||||
UpdateConnectionString(install.ConnectionString);
|
||||
UpdateDatabaseType(install.DatabaseType);
|
||||
|
||||
|
@ -491,6 +492,7 @@ namespace Oqtane.Infrastructure
|
|||
moduleDefinition.Categories = moduledef.Categories;
|
||||
// update version
|
||||
moduleDefinition.Version = versions[versions.Length - 1];
|
||||
moduleDefinition.ModifiedOn = DateTime.UtcNow;
|
||||
db.Entry(moduleDefinition).State = EntityState.Modified;
|
||||
db.SaveChanges();
|
||||
}
|
||||
|
@ -666,6 +668,11 @@ namespace Oqtane.Infrastructure
|
|||
return connectionString;
|
||||
}
|
||||
|
||||
public void UpdateInstallation()
|
||||
{
|
||||
_config.GetInstallationId();
|
||||
}
|
||||
|
||||
public void UpdateConnectionString(string connectionString)
|
||||
{
|
||||
connectionString = DenormalizeConnectionString(connectionString);
|
||||
|
@ -677,7 +684,10 @@ namespace Oqtane.Infrastructure
|
|||
|
||||
public void UpdateDatabaseType(string databaseType)
|
||||
{
|
||||
_configManager.AddOrUpdateSetting($"{SettingKeys.DatabaseSection}:{SettingKeys.DatabaseTypeKey}", databaseType, true);
|
||||
if (_config.GetSetting($"{SettingKeys.DatabaseSection}:{SettingKeys.DatabaseTypeKey}", "") != databaseType)
|
||||
{
|
||||
_configManager.AddOrUpdateSetting($"{SettingKeys.DatabaseSection}:{SettingKeys.DatabaseTypeKey}", databaseType, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEFMigrationsHistory(ISqlRepository sql, string connectionString, string databaseType, string version, bool isMaster)
|
||||
|
|
28
Oqtane.Server/Migrations/Master/06000201_AddThemeVersion.cs
Normal file
28
Oqtane.Server/Migrations/Master/06000201_AddThemeVersion.cs
Normal file
|
@ -0,0 +1,28 @@
|
|||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Oqtane.Databases.Interfaces;
|
||||
using Oqtane.Migrations.EntityBuilders;
|
||||
using Oqtane.Repository;
|
||||
|
||||
namespace Oqtane.Migrations.Master
|
||||
{
|
||||
[DbContext(typeof(MasterDBContext))]
|
||||
[Migration("Master.06.00.02.01")]
|
||||
public class AddThemeVersion : MultiDatabaseMigration
|
||||
{
|
||||
public AddThemeVersion(IDatabase database) : base(database)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
var themeEntityBuilder = new ThemeEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||
themeEntityBuilder.AddStringColumn("Version", 50, true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
// not implemented
|
||||
}
|
||||
}
|
||||
}
|
|
@ -101,6 +101,7 @@ namespace Oqtane.Repository
|
|||
ModuleDefinition.Resources = moduleDefinition.Resources;
|
||||
ModuleDefinition.IsEnabled = moduleDefinition.IsEnabled;
|
||||
ModuleDefinition.PackageName = moduleDefinition.PackageName;
|
||||
ModuleDefinition.Hash = Utilities.GenerateSimpleHash(moduleDefinition.ModifiedOn.ToString("yyyyMMddHHmm"));
|
||||
}
|
||||
|
||||
return ModuleDefinition;
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Diagnostics;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Metadata;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Oqtane.Infrastructure;
|
||||
|
@ -87,6 +88,7 @@ namespace Oqtane.Repository
|
|||
Theme.ThemeSettingsType = theme.ThemeSettingsType;
|
||||
Theme.ContainerSettingsType = theme.ContainerSettingsType;
|
||||
Theme.PackageName = theme.PackageName;
|
||||
Theme.Hash = Utilities.GenerateSimpleHash(theme.ModifiedOn.ToString("yyyyMMddHHmm"));
|
||||
Themes.Add(Theme);
|
||||
}
|
||||
|
||||
|
@ -126,6 +128,13 @@ namespace Oqtane.Repository
|
|||
}
|
||||
else
|
||||
{
|
||||
if (theme.Version != Theme.Version)
|
||||
{
|
||||
// update theme version
|
||||
theme.Version = Theme.Version;
|
||||
_db.SaveChanges();
|
||||
}
|
||||
|
||||
// override user customizable property values
|
||||
Theme.Name = (!string.IsNullOrEmpty(theme.Name)) ? theme.Name : Theme.Name;
|
||||
|
||||
|
|
|
@ -29,12 +29,13 @@ namespace Oqtane.Services
|
|||
private readonly ISettingRepository _settings;
|
||||
private readonly ITenantManager _tenantManager;
|
||||
private readonly ISyncManager _syncManager;
|
||||
private readonly IConfigManager _configManager;
|
||||
private readonly ILogManager _logger;
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly IHttpContextAccessor _accessor;
|
||||
private readonly string _private = "[PRIVATE]";
|
||||
|
||||
public ServerSiteService(ISiteRepository sites, IPageRepository pages, IThemeRepository themes, IPageModuleRepository pageModules, IModuleDefinitionRepository moduleDefinitions, ILanguageRepository languages, IUserPermissions userPermissions, ISettingRepository settings, ITenantManager tenantManager, ISyncManager syncManager, ILogManager logger, IMemoryCache cache, IHttpContextAccessor accessor)
|
||||
public ServerSiteService(ISiteRepository sites, IPageRepository pages, IThemeRepository themes, IPageModuleRepository pageModules, IModuleDefinitionRepository moduleDefinitions, ILanguageRepository languages, IUserPermissions userPermissions, ISettingRepository settings, ITenantManager tenantManager, ISyncManager syncManager, IConfigManager configManager, ILogManager logger, IMemoryCache cache, IHttpContextAccessor accessor)
|
||||
{
|
||||
_sites = sites;
|
||||
_pages = pages;
|
||||
|
@ -46,6 +47,7 @@ namespace Oqtane.Services
|
|||
_settings = settings;
|
||||
_tenantManager = tenantManager;
|
||||
_syncManager = syncManager;
|
||||
_configManager = configManager;
|
||||
_logger = logger;
|
||||
_cache = cache;
|
||||
_accessor = accessor;
|
||||
|
@ -143,6 +145,9 @@ namespace Oqtane.Services
|
|||
|
||||
// themes
|
||||
site.Themes = _themes.FilterThemes(_themes.GetThemes().ToList());
|
||||
|
||||
// installation date used for fingerprinting static assets
|
||||
site.Hash = Utilities.GenerateSimpleHash(_configManager.GetSetting("InstallationDate", DateTime.UtcNow.ToString("yyyyMMddHHmm")));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace Oqtane.Models
|
|||
public string Categories { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Version information of this Module based on the DLL / NuGet package.
|
||||
/// Version information of this Module based on the information stored in its assembly
|
||||
/// </summary>
|
||||
public string Version { get; set; }
|
||||
|
||||
|
@ -144,6 +144,9 @@ namespace Oqtane.Models
|
|||
[NotMapped]
|
||||
public bool IsPortable { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public string Hash { get; set; }
|
||||
|
||||
#region Deprecated Properties
|
||||
|
||||
[Obsolete("The Permissions property is deprecated. Use PermissionList instead", false)]
|
||||
|
|
|
@ -83,7 +83,21 @@ namespace Oqtane.Models
|
|||
/// </summary>
|
||||
public string Namespace { get; set; }
|
||||
|
||||
public Resource Clone(ResourceLevel level, string name)
|
||||
/// <summary>
|
||||
/// The version of the theme or module that declared the resource - only used in SiteRouter
|
||||
/// </summary>
|
||||
public string Version
|
||||
{
|
||||
set
|
||||
{
|
||||
if (!string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(Url) && !Url.Contains("?"))
|
||||
{
|
||||
Url += "?v=" + value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Resource Clone(ResourceLevel level, string name, string version)
|
||||
{
|
||||
var resource = new Resource();
|
||||
resource.ResourceType = ResourceType;
|
||||
|
@ -106,6 +120,7 @@ namespace Oqtane.Models
|
|||
}
|
||||
resource.Level = level;
|
||||
resource.Namespace = name;
|
||||
resource.Version = version;
|
||||
return resource;
|
||||
}
|
||||
|
||||
|
|
|
@ -187,6 +187,12 @@ namespace Oqtane.Models
|
|||
[NotMapped]
|
||||
public List<Theme> Themes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// hash code for static assets
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public string Hash { get; set; }
|
||||
|
||||
public Site Clone()
|
||||
{
|
||||
return new Site
|
||||
|
@ -227,7 +233,8 @@ namespace Oqtane.Models
|
|||
Settings = Settings.ToDictionary(setting => setting.Key, setting => setting.Value),
|
||||
Pages = Pages.ConvertAll(page => page.Clone()),
|
||||
Languages = Languages.ConvertAll(language => language.Clone()),
|
||||
Themes = Themes
|
||||
Themes = Themes,
|
||||
Hash = Hash
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -40,10 +40,13 @@ namespace Oqtane.Models
|
|||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
// additional ITheme properties
|
||||
[NotMapped]
|
||||
/// <summary>
|
||||
/// Version information of this Theme based on the information stored in its assembly
|
||||
/// </summary>
|
||||
public string Version { get; set; }
|
||||
|
||||
// additional ITheme properties
|
||||
|
||||
[NotMapped]
|
||||
public string Owner { get; set; }
|
||||
|
||||
|
@ -78,17 +81,25 @@ namespace Oqtane.Models
|
|||
// internal properties
|
||||
[NotMapped]
|
||||
public int SiteId { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public bool IsEnabled { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public string AssemblyName { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public List<ThemeControl> Themes { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public List<ThemeControl> Containers { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public string Template { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public string Hash { get; set; }
|
||||
|
||||
#region Obsolete Properties
|
||||
|
||||
[Obsolete("This property is obsolete. Use Themes instead.", false)]
|
||||
|
|
|
@ -575,7 +575,6 @@ namespace Oqtane.Shared
|
|||
}
|
||||
else if (expiryDate.HasValue)
|
||||
{
|
||||
// Include equality check here
|
||||
return currentUtcTime <= expiryDate.Value;
|
||||
}
|
||||
else
|
||||
|
@ -586,32 +585,40 @@ namespace Oqtane.Shared
|
|||
|
||||
public static bool ValidateEffectiveExpiryDates(DateTime? effectiveDate, DateTime? expiryDate)
|
||||
{
|
||||
// Treat DateTime.MinValue as null
|
||||
effectiveDate ??= DateTime.MinValue;
|
||||
expiryDate ??= DateTime.MinValue;
|
||||
|
||||
// Check if both effectiveDate and expiryDate have values
|
||||
if (effectiveDate != DateTime.MinValue && expiryDate != DateTime.MinValue)
|
||||
{
|
||||
return effectiveDate <= expiryDate;
|
||||
}
|
||||
// Check if only effectiveDate has a value
|
||||
else if (effectiveDate != DateTime.MinValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Check if only expiryDate has a value
|
||||
else if (expiryDate != DateTime.MinValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// If neither effectiveDate nor expiryDate has a value, consider the page/module visible
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GenerateSimpleHash(string text)
|
||||
{
|
||||
unchecked // prevent overflow exception
|
||||
{
|
||||
int hash = 23;
|
||||
foreach (char c in text)
|
||||
{
|
||||
hash = hash * 31 + c;
|
||||
}
|
||||
return hash.ToString("X8");
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("ContentUrl(Alias alias, int fileId) is deprecated. Use FileUrl(Alias alias, int fileId) instead.", false)]
|
||||
public static string ContentUrl(Alias alias, int fileId)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue
Block a user