move user workload from siterouter to app component to improve performance and 404 handling

This commit is contained in:
sbwalker
2025-12-05 08:40:30 -05:00
parent 23d14c62a5
commit a51f87d743
12 changed files with 91 additions and 39 deletions

View File

@@ -60,7 +60,7 @@
}
@((MarkupString)_headResources)
</head>
<body data-enhance-nav="@_enhancedNavigation.ToString().ToLower()">
<body @attributes="_bodyAttributes">
@if (string.IsNullOrEmpty(_message))
{
@if (_renderMode == RenderModes.Static)
@@ -97,7 +97,7 @@
private string _renderMode = RenderModes.Interactive;
private string _runtime = Runtimes.Server;
private bool _prerender = true;
private bool _enhancedNavigation = true;
Dictionary<string, object> _bodyAttributes { get; set; } = new();
private string _fingerprint = "";
private int _visitorId = -1;
private string _antiForgeryToken = "";
@@ -142,7 +142,10 @@
_renderMode = site.RenderMode;
_runtime = site.Runtime;
_prerender = site.Prerender;
_enhancedNavigation = site.EnhancedNavigation;
if (_renderMode == RenderModes.Static && !site.EnhancedNavigation)
{
_bodyAttributes.Add("data-enhance-nav", "false");
}
_fingerprint = site.Fingerprint;
var cookieConsentSettings = SettingService.GetSetting(site.Settings, "CookieConsent", string.Empty);
@@ -234,7 +237,7 @@
Site = site,
Page = page,
Modules = modules,
User = null,
User = site.User,
Uri = new Uri(url, UriKind.Absolute),
Route = route,
QueryString = Utilities.ParseQueryString(route.Query),
@@ -251,7 +254,6 @@
IsInternalNavigation = false,
RenderId = Guid.NewGuid(),
Refresh = true,
StatusCode = Context.Response.StatusCode,
AllowCookies = _allowCookies
};
}

View File

@@ -1,97 +0,0 @@
using System.Linq;
using System.Security.Claims;
using Oqtane.Shared;
namespace Oqtane.Extensions
{
public static class ClaimsPrincipalExtensions
{
// extension methods cannot be properties - the methods below must include a () suffix when referenced
public static string Username(this ClaimsPrincipal claimsPrincipal)
{
if (claimsPrincipal.HasClaim(item => item.Type == ClaimTypes.Name))
{
return claimsPrincipal.Claims.FirstOrDefault(item => item.Type == ClaimTypes.Name).Value;
}
else
{
return "";
}
}
public static int UserId(this ClaimsPrincipal claimsPrincipal)
{
if (claimsPrincipal.HasClaim(item => item.Type == ClaimTypes.NameIdentifier))
{
return int.Parse(claimsPrincipal.Claims.First(item => item.Type == ClaimTypes.NameIdentifier).Value);
}
else
{
return -1;
}
}
public static string[] Roles(this ClaimsPrincipal claimsPrincipal)
{
return claimsPrincipal.Claims.Where(item => item.Type == ClaimTypes.Role)
.Select(item => item.Value).ToArray();
}
public static string SiteKey(this ClaimsPrincipal claimsPrincipal)
{
if (claimsPrincipal.HasClaim(item => item.Type == Constants.SiteKeyClaimType))
{
return claimsPrincipal.Claims.FirstOrDefault(item => item.Type == Constants.SiteKeyClaimType).Value;
}
else
{
return "";
}
}
public static int TenantId(this ClaimsPrincipal claimsPrincipal)
{
var sitekey = SiteKey(claimsPrincipal);
if (!string.IsNullOrEmpty(sitekey) && sitekey.Contains(":"))
{
return int.Parse(sitekey.Split(':')[0]);
}
return -1;
}
public static int SiteId(this ClaimsPrincipal claimsPrincipal)
{
var sitekey = SiteKey(claimsPrincipal);
if (!string.IsNullOrEmpty(sitekey) && sitekey.Contains(":"))
{
return int.Parse(sitekey.Split(':')[1]);
}
return -1;
}
public static string SecurityStamp(this ClaimsPrincipal claimsPrincipal)
{
if (claimsPrincipal.HasClaim(item => item.Type == Constants.SecurityStampClaimType))
{
return claimsPrincipal.Claims.FirstOrDefault(item => item.Type == Constants.SecurityStampClaimType).Value;
}
else
{
return "";
}
}
public static bool IsOnlyInRole(this ClaimsPrincipal claimsPrincipal, string role)
{
var identity = claimsPrincipal.Identities.FirstOrDefault(item => item.AuthenticationType == Constants.AuthenticationScheme);
if (identity != null)
{
// check if user has role claim specified and no other role claims
return identity.Claims.Any(item => item.Type == ClaimTypes.Role && item.Value == role) &&
!identity.Claims.Any(item => item.Type == ClaimTypes.Role && item.Value != role);
}
return false;
}
}
}

View File

@@ -1,11 +0,0 @@
using System.Collections.Generic;
using Oqtane.Models;
namespace Oqtane.Infrastructure
{
public interface ISiteNamedOptions<TOptions>
where TOptions : class, new()
{
void Configure(string name, TOptions options, Alias alias, Dictionary<string, string> sitesettings);
}
}

View File

@@ -1,11 +0,0 @@
using System.Collections.Generic;
using Oqtane.Models;
namespace Oqtane.Infrastructure
{
public interface ISiteOptions<TOptions>
where TOptions : class, new()
{
void Configure(TOptions options, Alias alias, Dictionary<string, string> sitesettings);
}
}

View File

@@ -4,6 +4,12 @@ using Oqtane.Models;
namespace Oqtane.Infrastructure
{
public interface ISiteNamedOptions<TOptions>
where TOptions : class, new()
{
void Configure(string name, TOptions options, Alias alias, Dictionary<string, string> sitesettings);
}
public class SiteNamedOptions<TOptions> : ISiteNamedOptions<TOptions>
where TOptions : class, new()
{

View File

@@ -4,6 +4,12 @@ using Oqtane.Models;
namespace Oqtane.Infrastructure
{
public interface ISiteOptions<TOptions>
where TOptions : class, new()
{
void Configure(TOptions options, Alias alias, Dictionary<string, string> sitesettings);
}
public class SiteOptions<TOptions> : ISiteOptions<TOptions>
where TOptions : class, new()
{

View File

@@ -13,6 +13,7 @@ using Oqtane.Enums;
using Oqtane.Shared;
using System.Globalization;
using Oqtane.Extensions;
using Oqtane.Managers;
namespace Oqtane.Services
{
@@ -25,6 +26,7 @@ namespace Oqtane.Services
private readonly IPageModuleRepository _pageModules;
private readonly IModuleDefinitionRepository _moduleDefinitions;
private readonly ILanguageRepository _languages;
private readonly IUserManager _userManager;
private readonly IUserPermissions _userPermissions;
private readonly ISettingRepository _settings;
private readonly ITenantManager _tenantManager;
@@ -35,7 +37,7 @@ namespace Oqtane.Services
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, IConfigManager configManager, ILogManager logger, IMemoryCache cache, IHttpContextAccessor accessor)
public ServerSiteService(ISiteRepository sites, IPageRepository pages, IThemeRepository themes, IPageModuleRepository pageModules, IModuleDefinitionRepository moduleDefinitions, ILanguageRepository languages, IUserManager userManager, IUserPermissions userPermissions, ISettingRepository settings, ITenantManager tenantManager, ISyncManager syncManager, IConfigManager configManager, ILogManager logger, IMemoryCache cache, IHttpContextAccessor accessor)
{
_sites = sites;
_pages = pages;
@@ -43,6 +45,7 @@ namespace Oqtane.Services
_pageModules = pageModules;
_moduleDefinitions = moduleDefinitions;
_languages = languages;
_userManager = userManager;
_userPermissions = userPermissions;
_settings = settings;
_tenantManager = tenantManager;
@@ -146,6 +149,12 @@ namespace Oqtane.Services
// themes
site.Themes = _themes.FilterThemes(_themes.GetThemes(site.SiteId).ToList());
// user
if (_accessor.HttpContext.User.IsAuthenticated())
{
site.User = _userManager.GetUser(_accessor.HttpContext.User.UserId(), site.SiteId);
}
// installation date used for fingerprinting static assets
site.Fingerprint = Utilities.GenerateSimpleHash(_configManager.GetSetting("InstallationDate", DateTime.UtcNow.ToString("yyyyMMddHHmm")));