From 18730c5e5351020e059dfec6887b279f7eed9828 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Thu, 26 Feb 2026 11:03:58 -0500 Subject: [PATCH 01/20] add some defensive logic in file handler --- Oqtane.Server/Pages/Files.cshtml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Oqtane.Server/Pages/Files.cshtml.cs b/Oqtane.Server/Pages/Files.cshtml.cs index f01cd0b7..2c7d5ee6 100644 --- a/Oqtane.Server/Pages/Files.cshtml.cs +++ b/Oqtane.Server/Pages/Files.cshtml.cs @@ -48,7 +48,7 @@ namespace Oqtane.Pages public IActionResult OnGet(string path) { - if (string.IsNullOrWhiteSpace(path)) + if (string.IsNullOrWhiteSpace(path) || _alias == null) { HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; return BrokenFile(); From f1934028a11ccfa7d4cc587917f98c35af0d5018 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Fri, 27 Feb 2026 14:15:03 -0500 Subject: [PATCH 02/20] use visitor tracking filter with url mapping --- Oqtane.Server/Components/App.razor | 58 +++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/Oqtane.Server/Components/App.razor b/Oqtane.Server/Components/App.razor index a55b28a1..e9d09249 100644 --- a/Oqtane.Server/Components/App.razor +++ b/Oqtane.Server/Components/App.razor @@ -266,6 +266,30 @@ private void HandlePageNotFound(Site site, Page page, Route route) { + string useragent = (Context.Request.Headers[HeaderNames.UserAgent] != StringValues.Empty) ? Context.Request.Headers[HeaderNames.UserAgent] : "(none)"; + useragent = (useragent.Length > 256) ? useragent.Substring(0, 256) : useragent; + + // filter + var settings = Context.GetSiteSettings(); + var filter = settings.GetValue("VisitorFilter", Constants.DefaultVisitorFilter); + foreach (string term in filter.ToLower().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(sValue => sValue.Trim()).ToArray()) + { + if (_remoteIPAddress.ToLower().Contains(term) || useragent.ToLower().Contains(term)) + { + // handle not found request in static mode + if (_renderMode == RenderModes.Static) + { + NavigationManager.NotFound(); + } + else + { + // redirect to 404 page + NavigationManager.NavigateTo(route.SiteUrl + "/404", true); + } + return; + } + } + // referrer will only be set if the link originated externally string referrer = (Context.Request.Headers[HeaderNames.Referer] != StringValues.Empty) ? Context.Request.Headers[HeaderNames.Referer] : ""; @@ -564,23 +588,6 @@ } } - private void SetLocalizationCookie(string cookieValue) - { - var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions - { - Expires = DateTimeOffset.UtcNow.AddYears(1), - SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Lax, // Set SameSite attribute - Secure = true, // Ensure the cookie is only sent over HTTPS - HttpOnly = false // cookie is updated using JS Interop in Interactive render mode - }; - - Context.Response.Cookies.Append( - Shared.CookieRequestCultureProvider.DefaultCookieName, - cookieValue, - cookieOptions - ); - } - private async Task> GetPageResources(Alias alias, Site site, Page page, List modules, int moduleid, string action) { var resources = new List(); @@ -852,4 +859,21 @@ SetLocalizationCookie(cultureCookie); } } + + private void SetLocalizationCookie(string cookieValue) + { + var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions + { + Expires = DateTimeOffset.UtcNow.AddYears(1), + SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Lax, // Set SameSite attribute + Secure = true, // Ensure the cookie is only sent over HTTPS + HttpOnly = false // cookie is updated using JS Interop in Interactive render mode + }; + + Context.Response.Cookies.Append( + Shared.CookieRequestCultureProvider.DefaultCookieName, + cookieValue, + cookieOptions + ); + } } From d1b40f0603458f3f6e89eb2f02561ece44f7378b Mon Sep 17 00:00:00 2001 From: sbwalker Date: Fri, 27 Feb 2026 14:24:26 -0500 Subject: [PATCH 03/20] fix #6087 - module category filter --- Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor | 2 +- .../Themes/Controls/Theme/ControlPanelInteractive.razor | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor index bbb2698e..0fd25300 100644 --- a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor +++ b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor @@ -130,7 +130,7 @@ else private async Task LoadModuleDefinitions() { - _moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(_category)).ToList(); + _moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Split(',', StringSplitOptions.RemoveEmptyEntries).Contains(_category)).ToList(); _packages = await PackageService.GetPackageUpdatesAsync("module"); } diff --git a/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor b/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor index ffd54afa..958a0345 100644 --- a/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor +++ b/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor @@ -303,7 +303,7 @@ _containers = ThemeService.GetContainerControls(PageState.Site.Themes, PageState.Page.ThemeType); _containerType = PageState.Site.DefaultContainerType; _allModuleDefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Page.SiteId); - _moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(_category)).ToList(); + _moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Split(',', StringSplitOptions.RemoveEmptyEntries).Contains(_category)).ToList(); _categories = _allModuleDefinitions.SelectMany(m => m.Categories.Split(',', StringSplitOptions.RemoveEmptyEntries)).Distinct().Where(item => item != "Headless").ToList(); _siteGroups = await SiteGroupService.GetSiteGroupsAsync(PageState.Site.SiteId); } @@ -312,7 +312,7 @@ private void CategoryChanged(ChangeEventArgs e) { _category = (string)e.Value; - _moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(_category)).ToList(); + _moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Split(',', StringSplitOptions.RemoveEmptyEntries).Contains(_category)).ToList(); _moduleDefinitionName = "-"; _message = ""; } From cf61a58b4cc03352aca5cd87e628595dd0c6f887 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Fri, 27 Feb 2026 14:36:43 -0500 Subject: [PATCH 04/20] do not reduce length of user agent --- Oqtane.Server/Components/App.razor | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Oqtane.Server/Components/App.razor b/Oqtane.Server/Components/App.razor index e9d09249..20d80d11 100644 --- a/Oqtane.Server/Components/App.razor +++ b/Oqtane.Server/Components/App.razor @@ -266,10 +266,8 @@ private void HandlePageNotFound(Site site, Page page, Route route) { - string useragent = (Context.Request.Headers[HeaderNames.UserAgent] != StringValues.Empty) ? Context.Request.Headers[HeaderNames.UserAgent] : "(none)"; - useragent = (useragent.Length > 256) ? useragent.Substring(0, 256) : useragent; - // filter + string useragent = (Context.Request.Headers[HeaderNames.UserAgent] != StringValues.Empty) ? Context.Request.Headers[HeaderNames.UserAgent] : "(none)"; var settings = Context.GetSiteSettings(); var filter = settings.GetValue("VisitorFilter", Constants.DefaultVisitorFilter); foreach (string term in filter.ToLower().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(sValue => sValue.Trim()).ToArray()) From 6160941aee0753c0939a6b0193e92c1e6923960c Mon Sep 17 00:00:00 2001 From: sbwalker Date: Mon, 2 Mar 2026 13:47:01 -0500 Subject: [PATCH 05/20] fix #6091 - Add page route incorrect --- .../Themes/Controls/Theme/ControlPanelInteractive.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor b/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor index 958a0345..72d14be6 100644 --- a/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor +++ b/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor @@ -521,7 +521,7 @@ case "Edit": // get page management moduleid moduleId = int.Parse(PageState.Site.Settings[Constants.PageManagementModule]); - NavigationManager.NavigateTo(Utilities.EditUrl(PageState.Alias.Path, "admin/pages", moduleId, "Edit", $"id={PageState.Page.PageId}&returnurl={WebUtility.UrlEncode(PageState.Route.PathAndQuery)}")); + NavigationManager.NavigateTo(Utilities.EditUrl(PageState.Alias.Path, "admin/pages", moduleId, location, $"id={PageState.Page.PageId}&returnurl={WebUtility.UrlEncode(PageState.Route.PathAndQuery)}")); break; case "Copy": // get page management moduleid From e65f61bd6508f73c43e7746b9f8ed048bad78a93 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Tue, 3 Mar 2026 07:54:45 -0500 Subject: [PATCH 06/20] increment version to 10.1.1 --- Directory.Build.props | 4 ++-- Oqtane.Application/Client/Oqtane.Application.Client.csproj | 2 +- Oqtane.Application/Oqtane.Application.Template.nuspec | 2 +- Oqtane.Application/Server/Oqtane.Application.Server.csproj | 2 +- Oqtane.Application/Shared/Oqtane.Application.Shared.csproj | 2 +- Oqtane.Maui/Oqtane.Maui.csproj | 2 +- Oqtane.Package/Oqtane.Client.nuspec | 4 ++-- Oqtane.Package/Oqtane.Framework.nuspec | 6 +++--- Oqtane.Package/Oqtane.Server.nuspec | 4 ++-- Oqtane.Package/Oqtane.Shared.nuspec | 4 ++-- Oqtane.Package/Oqtane.Updater.nuspec | 4 ++-- Oqtane.Package/install.ps1 | 2 +- Oqtane.Package/upgrade.ps1 | 2 +- Oqtane.Shared/Shared/Constants.cs | 4 ++-- 14 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index e1f15325..47e4da1a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,7 +2,7 @@ net10.0 Debug;Release - 10.1.0 + 10.1.1 Oqtane Shaun Walker .NET Foundation @@ -10,7 +10,7 @@ .NET Foundation https://www.oqtane.org https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE - https://github.com/oqtane/oqtane.framework/releases/tag/v10.1.0 + https://github.com/oqtane/oqtane.framework/releases/tag/v10.1.1 https://github.com/oqtane/oqtane.framework Git diff --git a/Oqtane.Application/Client/Oqtane.Application.Client.csproj b/Oqtane.Application/Client/Oqtane.Application.Client.csproj index 8874d9db..1d618b2d 100644 --- a/Oqtane.Application/Client/Oqtane.Application.Client.csproj +++ b/Oqtane.Application/Client/Oqtane.Application.Client.csproj @@ -23,7 +23,7 @@ - + diff --git a/Oqtane.Application/Oqtane.Application.Template.nuspec b/Oqtane.Application/Oqtane.Application.Template.nuspec index 9ba1ed74..a5acb9a9 100644 --- a/Oqtane.Application/Oqtane.Application.Template.nuspec +++ b/Oqtane.Application/Oqtane.Application.Template.nuspec @@ -2,7 +2,7 @@ Oqtane.Application.Template - 10.1.0 + 10.1.1 Oqtane Application Template For Blazor Shaun Walker false diff --git a/Oqtane.Application/Server/Oqtane.Application.Server.csproj b/Oqtane.Application/Server/Oqtane.Application.Server.csproj index 3526407a..c8f34122 100644 --- a/Oqtane.Application/Server/Oqtane.Application.Server.csproj +++ b/Oqtane.Application/Server/Oqtane.Application.Server.csproj @@ -33,7 +33,7 @@ - + diff --git a/Oqtane.Application/Shared/Oqtane.Application.Shared.csproj b/Oqtane.Application/Shared/Oqtane.Application.Shared.csproj index 7689e461..636ff9bf 100644 --- a/Oqtane.Application/Shared/Oqtane.Application.Shared.csproj +++ b/Oqtane.Application/Shared/Oqtane.Application.Shared.csproj @@ -11,7 +11,7 @@ - + diff --git a/Oqtane.Maui/Oqtane.Maui.csproj b/Oqtane.Maui/Oqtane.Maui.csproj index 18f449d8..4c346167 100644 --- a/Oqtane.Maui/Oqtane.Maui.csproj +++ b/Oqtane.Maui/Oqtane.Maui.csproj @@ -18,7 +18,7 @@ com.oqtane.maui - 10.1.0 + 10.1.1 1 diff --git a/Oqtane.Package/Oqtane.Client.nuspec b/Oqtane.Package/Oqtane.Client.nuspec index 42696e16..cfd729a4 100644 --- a/Oqtane.Package/Oqtane.Client.nuspec +++ b/Oqtane.Package/Oqtane.Client.nuspec @@ -2,7 +2,7 @@ Oqtane.Client - 10.1.0 + 10.1.1 Shaun Walker .NET Foundation Oqtane Framework @@ -12,7 +12,7 @@ false MIT https://github.com/oqtane/oqtane.framework - https://github.com/oqtane/oqtane.framework/releases/tag/v10.1.0 + https://github.com/oqtane/oqtane.framework/releases/tag/v10.1.1 readme.md icon.png oqtane diff --git a/Oqtane.Package/Oqtane.Framework.nuspec b/Oqtane.Package/Oqtane.Framework.nuspec index 25f116ad..f2e8a58e 100644 --- a/Oqtane.Package/Oqtane.Framework.nuspec +++ b/Oqtane.Package/Oqtane.Framework.nuspec @@ -2,7 +2,7 @@ Oqtane.Framework - 10.1.0 + 10.1.1 Shaun Walker .NET Foundation Oqtane Framework @@ -11,8 +11,8 @@ .NET Foundation false MIT - https://github.com/oqtane/oqtane.framework/releases/download/v10.1.0/Oqtane.Framework.10.1.0.Upgrade.zip - https://github.com/oqtane/oqtane.framework/releases/tag/v10.1.0 + https://github.com/oqtane/oqtane.framework/releases/download/v10.1.1/Oqtane.Framework.10.1.1.Upgrade.zip + https://github.com/oqtane/oqtane.framework/releases/tag/v10.1.1 readme.md icon.png oqtane framework diff --git a/Oqtane.Package/Oqtane.Server.nuspec b/Oqtane.Package/Oqtane.Server.nuspec index 4caf53a3..7264ca22 100644 --- a/Oqtane.Package/Oqtane.Server.nuspec +++ b/Oqtane.Package/Oqtane.Server.nuspec @@ -2,7 +2,7 @@ Oqtane.Server - 10.1.0 + 10.1.1 Shaun Walker .NET Foundation Oqtane Framework @@ -12,7 +12,7 @@ false MIT https://github.com/oqtane/oqtane.framework - https://github.com/oqtane/oqtane.framework/releases/tag/v10.1.0 + https://github.com/oqtane/oqtane.framework/releases/tag/v10.1.1 readme.md icon.png oqtane diff --git a/Oqtane.Package/Oqtane.Shared.nuspec b/Oqtane.Package/Oqtane.Shared.nuspec index b1374aea..50925cbb 100644 --- a/Oqtane.Package/Oqtane.Shared.nuspec +++ b/Oqtane.Package/Oqtane.Shared.nuspec @@ -2,7 +2,7 @@ Oqtane.Shared - 10.1.0 + 10.1.1 Shaun Walker .NET Foundation Oqtane Framework @@ -12,7 +12,7 @@ false MIT https://github.com/oqtane/oqtane.framework - https://github.com/oqtane/oqtane.framework/releases/tag/v10.1.0 + https://github.com/oqtane/oqtane.framework/releases/tag/v10.1.1 readme.md icon.png oqtane diff --git a/Oqtane.Package/Oqtane.Updater.nuspec b/Oqtane.Package/Oqtane.Updater.nuspec index 840f3de0..d1d8e2ef 100644 --- a/Oqtane.Package/Oqtane.Updater.nuspec +++ b/Oqtane.Package/Oqtane.Updater.nuspec @@ -2,7 +2,7 @@ Oqtane.Updater - 10.1.0 + 10.1.1 Shaun Walker .NET Foundation Oqtane Framework @@ -12,7 +12,7 @@ false MIT https://github.com/oqtane/oqtane.framework - https://github.com/oqtane/oqtane.framework/releases/tag/v10.1.0 + https://github.com/oqtane/oqtane.framework/releases/tag/v10.1.1 readme.md icon.png oqtane diff --git a/Oqtane.Package/install.ps1 b/Oqtane.Package/install.ps1 index 1849738e..b2611634 100644 --- a/Oqtane.Package/install.ps1 +++ b/Oqtane.Package/install.ps1 @@ -1 +1 @@ -Compress-Archive -Path "..\Oqtane.Server\bin\Release\net10.0\publish\*" -DestinationPath "Oqtane.Framework.10.1.0.Install.zip" -Force +Compress-Archive -Path "..\Oqtane.Server\bin\Release\net10.0\publish\*" -DestinationPath "Oqtane.Framework.10.1.1.Install.zip" -Force diff --git a/Oqtane.Package/upgrade.ps1 b/Oqtane.Package/upgrade.ps1 index dba48f9b..4a84e86e 100644 --- a/Oqtane.Package/upgrade.ps1 +++ b/Oqtane.Package/upgrade.ps1 @@ -1 +1 @@ -Compress-Archive -Path "..\Oqtane.Server\bin\Release\net10.0\publish\*" -DestinationPath "Oqtane.Framework.10.1.0.Upgrade.zip" -Force +Compress-Archive -Path "..\Oqtane.Server\bin\Release\net10.0\publish\*" -DestinationPath "Oqtane.Framework.10.1.1.Upgrade.zip" -Force diff --git a/Oqtane.Shared/Shared/Constants.cs b/Oqtane.Shared/Shared/Constants.cs index 2df66252..e2c93076 100644 --- a/Oqtane.Shared/Shared/Constants.cs +++ b/Oqtane.Shared/Shared/Constants.cs @@ -4,8 +4,8 @@ namespace Oqtane.Shared { public class Constants { - public static readonly string Version = "10.1.0"; - public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0,2.2.0,2.3.0,2.3.1,3.0.0,3.0.1,3.0.2,3.0.3,3.1.0,3.1.1,3.1.2,3.1.3,3.1.4,3.2.0,3.2.1,3.3.0,3.3.1,3.4.0,3.4.1,3.4.2,3.4.3,4.0.0,4.0.1,4.0.2,4.0.3,4.0.4,4.0.5,4.0.6,5.0.0,5.0.1,5.0.2,5.0.3,5.1.0,5.1.1,5.1.2,5.2.0,5.2.1,5.2.2,5.2.3,5.2.4,6.0.0,6.0.1,6.1.0,6.1.1,6.1.2,6.1.3,6.1.4,6.1.5,6.2.0,6.2.1,10.0.0,10.0.1,10.0.2,10.0.3,10.0.4,10.1.0"; + public static readonly string Version = "10.1.1"; + public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0,2.2.0,2.3.0,2.3.1,3.0.0,3.0.1,3.0.2,3.0.3,3.1.0,3.1.1,3.1.2,3.1.3,3.1.4,3.2.0,3.2.1,3.3.0,3.3.1,3.4.0,3.4.1,3.4.2,3.4.3,4.0.0,4.0.1,4.0.2,4.0.3,4.0.4,4.0.5,4.0.6,5.0.0,5.0.1,5.0.2,5.0.3,5.1.0,5.1.1,5.1.2,5.2.0,5.2.1,5.2.2,5.2.3,5.2.4,6.0.0,6.0.1,6.1.0,6.1.1,6.1.2,6.1.3,6.1.4,6.1.5,6.2.0,6.2.1,10.0.0,10.0.1,10.0.2,10.0.3,10.0.4,10.1.0,10.1.1"; public const string PackageId = "Oqtane.Framework"; public const string ClientId = "Oqtane.Client"; public const string UpdaterPackageId = "Oqtane.Updater"; From 72542f01468f184b5f7e24daf68d8d222b56e8a3 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Tue, 3 Mar 2026 15:48:25 -0500 Subject: [PATCH 07/20] allow page attributes to support alias names --- .../Repository/ModuleDefinitionRepository.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs index fd1e11e7..ae68b41c 100644 --- a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs +++ b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs @@ -448,11 +448,20 @@ namespace Oqtane.Repository var route = routeAttributes.First().Template; if (!string.IsNullOrEmpty(route)) { - // @page "/route" (note that nested routes are not permitted) + // @page "/path" or @page "alias/path" (note that nested paths are not permitted) var pageTemplate = new PageTemplate(); - pageTemplate.AliasName = "*"; + if (route.StartsWith("/")) + { + pageTemplate.AliasName = "*"; // all sites + pageTemplate.Path = route.Substring(1); + } + else // route contains an alias name + { + var lastSlash = route.LastIndexOf('/'); + pageTemplate.AliasName = route.Substring(0, lastSlash); + pageTemplate.Path = route.Substring(lastSlash + 1); + } pageTemplate.Version = "*"; - pageTemplate.Path = route.Substring(1); pageTemplate.Update = false; pageTemplate.PageTemplateModules = new List(); From aac1bb582baa11acc5db4c721d3a91d2e94b3dc6 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Tue, 3 Mar 2026 17:32:19 -0500 Subject: [PATCH 08/20] copy page should copy page settings --- Oqtane.Server/Controllers/PageController.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Oqtane.Server/Controllers/PageController.cs b/Oqtane.Server/Controllers/PageController.cs index a23ba365..80300154 100644 --- a/Oqtane.Server/Controllers/PageController.cs +++ b/Oqtane.Server/Controllers/PageController.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.Linq; using System.Net; -using System.Security; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Oqtane.Enums; @@ -509,6 +508,20 @@ namespace Oqtane.Controllers var toPage = _pages.GetPage(toPageId); if (toPage != null && toPage.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, PermissionNames.View, toPage.PermissionList)) { + // copy page settings + var settings = _settings.GetSettings(EntityNames.Page, fromPage.PageId).ToList(); + foreach (var setting in settings) + { + _settings.AddSetting(new Setting + { + EntityName = setting.EntityName, + EntityId = toPage.PageId, + SettingName = setting.SettingName, + SettingValue = setting.SettingValue, + IsPrivate = setting.IsPrivate + }); + } + // copy modules List pageModules = _pageModules.GetPageModules(fromPage.SiteId).ToList(); foreach (PageModule pm in pageModules.Where(item => item.PageId == fromPage.PageId && !item.Module.AllPages && !item.IsDeleted)) @@ -544,6 +557,8 @@ namespace Oqtane.Controllers }).ToList(); module = _modules.AddModule(module); + + // copy module content (includes settings) string content = _modules.ExportModule(pm.ModuleId); if (content != "") { From 147ee8b1e7b18c4af4c290caeea21605c824abff Mon Sep 17 00:00:00 2001 From: sbwalker Date: Wed, 4 Mar 2026 09:09:07 -0500 Subject: [PATCH 09/20] resolve issue with Change Detection group --- Oqtane.Server/Infrastructure/Jobs/SynchronizationJob.cs | 6 +++++- Oqtane.Server/Repository/SettingRepository.cs | 5 ----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Oqtane.Server/Infrastructure/Jobs/SynchronizationJob.cs b/Oqtane.Server/Infrastructure/Jobs/SynchronizationJob.cs index 24e3ed19..b3d4ac08 100644 --- a/Oqtane.Server/Infrastructure/Jobs/SynchronizationJob.cs +++ b/Oqtane.Server/Infrastructure/Jobs/SynchronizationJob.cs @@ -617,7 +617,11 @@ namespace Oqtane.Infrastructure private string SynchronizeModules(IServiceProvider provider, ISettingRepository settingRepository, IPageModuleRepository pageModuleRepository, IModuleRepository moduleRepository, SiteGroupMember siteGroupMember, List primaryPageModules, List secondaryPageModules, Page primaryPage, Page secondaryPage, int secondarySiteId) { var log = ""; - var removePageModules = secondaryPageModules.Where(item => item.PageId == secondaryPage.PageId).ToList(); + var removePageModules = new List(); + if (secondaryPage != null) + { + removePageModules = secondaryPageModules.Where(item => item.PageId == secondaryPage.PageId).ToList(); + } // iterate through primary modules on primary page foreach (var primaryPageModule in primaryPageModules.Where(item => item.PageId == primaryPage.PageId)) diff --git a/Oqtane.Server/Repository/SettingRepository.cs b/Oqtane.Server/Repository/SettingRepository.cs index f8bf4403..b2124298 100644 --- a/Oqtane.Server/Repository/SettingRepository.cs +++ b/Oqtane.Server/Repository/SettingRepository.cs @@ -1,14 +1,9 @@ -using System; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; -using Oqtane.Enums; using Oqtane.Infrastructure; using Oqtane.Models; -using Oqtane.Modules.Admin.Users; using Oqtane.Shared; namespace Oqtane.Repository From ef92a889082b5a954f6b52ef8af91403ea3f86c0 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Wed, 4 Mar 2026 09:59:52 -0500 Subject: [PATCH 10/20] prevent update of linked SiteGroup --- Oqtane.Server/Repository/SiteGroupMemberRepository.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Oqtane.Server/Repository/SiteGroupMemberRepository.cs b/Oqtane.Server/Repository/SiteGroupMemberRepository.cs index 82efb37a..3995338b 100644 --- a/Oqtane.Server/Repository/SiteGroupMemberRepository.cs +++ b/Oqtane.Server/Repository/SiteGroupMemberRepository.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.EntityFrameworkCore; using Oqtane.Models; +using Radzen; namespace Oqtane.Repository { @@ -51,6 +52,7 @@ namespace Oqtane.Repository { using var db = _dbContextFactory.CreateDbContext(); db.Entry(siteGroupMember).State = EntityState.Modified; + db.Entry(siteGroupMember.SiteGroup).State = EntityState.Unchanged; // prevent update of linked entity db.SaveChanges(); return siteGroupMember; } From 91b15b5e2a1f0820f65b9d5ce71e7191e452a603 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Wed, 4 Mar 2026 10:02:06 -0500 Subject: [PATCH 11/20] remove unnecessary using --- Oqtane.Server/Repository/SiteGroupMemberRepository.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Oqtane.Server/Repository/SiteGroupMemberRepository.cs b/Oqtane.Server/Repository/SiteGroupMemberRepository.cs index 3995338b..e0d1ac78 100644 --- a/Oqtane.Server/Repository/SiteGroupMemberRepository.cs +++ b/Oqtane.Server/Repository/SiteGroupMemberRepository.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using Microsoft.EntityFrameworkCore; using Oqtane.Models; -using Radzen; namespace Oqtane.Repository { From 8de67fdaec047502d66d8ce66cfa27188317e69f Mon Sep 17 00:00:00 2001 From: sbwalker Date: Wed, 4 Mar 2026 10:31:21 -0500 Subject: [PATCH 12/20] Global Replace should include settings --- .../Modules/Admin/GlobalReplace/Index.razor | 6 +-- .../Modules/Admin/GlobalReplace/Index.resx | 12 ++--- .../SiteTasks/GlobalReplaceTask.cs | 45 ++++++++++++++++++- 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/GlobalReplace/Index.razor b/Oqtane.Client/Modules/Admin/GlobalReplace/Index.razor index dff7e341..a62d686b 100644 --- a/Oqtane.Client/Modules/Admin/GlobalReplace/Index.razor +++ b/Oqtane.Client/Modules/Admin/GlobalReplace/Index.razor @@ -28,7 +28,7 @@
- +
@@ -46,7 +46,7 @@
- +