From 53b837e763cfced48a08417fc0c810b6556d477e Mon Sep 17 00:00:00 2001 From: sbwalker Date: Mon, 28 Apr 2025 12:34:48 -0400 Subject: [PATCH 1/8] fix #5229 - move IServerStartup.Configure execution until later so that it is possible to register custom endpoints --- Oqtane.Server/Infrastructure/Middleware/TenantMiddleware.cs | 4 ---- Oqtane.Server/Startup.cs | 6 +++--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Oqtane.Server/Infrastructure/Middleware/TenantMiddleware.cs b/Oqtane.Server/Infrastructure/Middleware/TenantMiddleware.cs index 1c2ec3c9..fe0210fd 100644 --- a/Oqtane.Server/Infrastructure/Middleware/TenantMiddleware.cs +++ b/Oqtane.Server/Infrastructure/Middleware/TenantMiddleware.cs @@ -23,10 +23,6 @@ namespace Oqtane.Infrastructure var config = context.RequestServices.GetService(typeof(IConfigManager)) as IConfigManager; string path = context.Request.Path.ToString(); - // note that in order to support Alias subfolders we used to ignore Blazor framework requests... - // but this does not work in static rendering as the web UI request originates from /_blazor - //if (config.IsInstalled() && !path.StartsWith("/_")) - if (config.IsInstalled()) { // get alias (note that this also sets SiteState.Alias) diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs index 51b60555..b51609ae 100644 --- a/Oqtane.Server/Startup.cs +++ b/Oqtane.Server/Startup.cs @@ -195,9 +195,6 @@ namespace Oqtane app.UseHsts(); } - // execute any IServerStartup logic - app.ConfigureOqtaneAssemblies(env); - // allow oqtane localization middleware app.UseOqtaneLocalization(); @@ -248,6 +245,9 @@ namespace Oqtane .AddAdditionalAssemblies(typeof(SiteRouter).Assembly); }); + // execute any IServerStartup logic + app.ConfigureOqtaneAssemblies(env); + // simulate the fallback routing approach of traditional Blazor - allowing the custom SiteRouter to handle all routing concerns app.UseEndpoints(endpoints => { From dc926bf8387a0898e74b4acbb7a3f8891eb06904 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Mon, 28 Apr 2025 12:42:50 -0400 Subject: [PATCH 2/8] add a convenience method to get a setting value server-side --- .../Repository/Interfaces/ISettingRepository.cs | 1 + Oqtane.Server/Repository/SettingRepository.cs | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/Oqtane.Server/Repository/Interfaces/ISettingRepository.cs b/Oqtane.Server/Repository/Interfaces/ISettingRepository.cs index 5c231806..febb7c5c 100644 --- a/Oqtane.Server/Repository/Interfaces/ISettingRepository.cs +++ b/Oqtane.Server/Repository/Interfaces/ISettingRepository.cs @@ -13,5 +13,6 @@ namespace Oqtane.Repository Setting GetSetting(string entityName, int entityId, string settingName); void DeleteSetting(string entityName, int settingId); void DeleteSettings(string entityName, int entityId); + string GetSettingValue(List settings, string settingName, string defaultValue); } } diff --git a/Oqtane.Server/Repository/SettingRepository.cs b/Oqtane.Server/Repository/SettingRepository.cs index 0ca28d50..4fc7c70e 100644 --- a/Oqtane.Server/Repository/SettingRepository.cs +++ b/Oqtane.Server/Repository/SettingRepository.cs @@ -165,6 +165,19 @@ namespace Oqtane.Repository ManageCache(entityName); } + public string GetSettingValue(List settings, string settingName, string defaultValue) + { + var setting = settings.FirstOrDefault(item => item.SettingName == settingName); + if (setting != null) + { + return setting.SettingValue; + } + else + { + return defaultValue; + } + } + private bool IsMaster(string EntityName) { return (EntityName == EntityNames.ModuleDefinition || EntityName == EntityNames.Host); From feee8def6f72c0406e7b5a1231e7db0fe0dc66dd Mon Sep 17 00:00:00 2001 From: Leigh Pointer Date: Tue, 29 Apr 2025 09:50:15 +0200 Subject: [PATCH 3/8] GetUrlParameters crash The _urlparametersstate variable is not initialized so in GetUrlParameters it causes a crash --- Oqtane.Client/Modules/ModuleBase.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Oqtane.Client/Modules/ModuleBase.cs b/Oqtane.Client/Modules/ModuleBase.cs index b97b229b..5bbfc855 100644 --- a/Oqtane.Client/Modules/ModuleBase.cs +++ b/Oqtane.Client/Modules/ModuleBase.cs @@ -17,7 +17,7 @@ namespace Oqtane.Modules public abstract class ModuleBase : ComponentBase, IModuleControl { private Logger _logger; - private string _urlparametersstate; + private string _urlparametersstate = string.Empty; private Dictionary _urlparameters; private bool _scriptsloaded = false; @@ -62,7 +62,7 @@ namespace Oqtane.Modules public Dictionary UrlParameters { get { - if (_urlparametersstate == null || _urlparametersstate != PageState.UrlParameters) + if (string.IsNullOrEmpty(_urlparametersstate) || _urlparametersstate != PageState.UrlParameters) { _urlparametersstate = PageState.UrlParameters; _urlparameters = GetUrlParameters(UrlParametersTemplate); From 753ab3bdd75f7c7db263e271be8bdccae7083878 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Wed, 30 Apr 2025 13:46:52 -0400 Subject: [PATCH 4/8] resolve issue with host setting overrides --- .../Infrastructure/Jobs/NotificationJob.cs | 2 +- .../Middleware/TenantMiddleware.cs | 2 +- .../Interfaces/ISettingRepository.cs | 2 ++ Oqtane.Server/Repository/SettingRepository.cs | 33 ++++++++++--------- Oqtane.Server/Services/SiteService.cs | 2 +- 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs b/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs index d65acb0a..bfee3066 100644 --- a/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs +++ b/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs @@ -40,7 +40,7 @@ namespace Oqtane.Infrastructure log += "Processing Notifications For Site: " + site.Name + "
"; // get site settings - List sitesettings = settingRepository.GetSettings(EntityNames.Site, site.SiteId).ToList(); + List sitesettings = settingRepository.GetSettings(EntityNames.Site, site.SiteId, EntityNames.Host, -1).ToList(); Dictionary settings = GetSettings(sitesettings); if (!site.IsDeleted && (!settings.ContainsKey("SMTPEnabled") || settings["SMTPEnabled"] == "True")) { diff --git a/Oqtane.Server/Infrastructure/Middleware/TenantMiddleware.cs b/Oqtane.Server/Infrastructure/Middleware/TenantMiddleware.cs index fe0210fd..13b74176 100644 --- a/Oqtane.Server/Infrastructure/Middleware/TenantMiddleware.cs +++ b/Oqtane.Server/Infrastructure/Middleware/TenantMiddleware.cs @@ -39,7 +39,7 @@ namespace Oqtane.Infrastructure var sitesettings = cache.GetOrCreate(Constants.HttpContextSiteSettingsKey + alias.SiteKey, entry => { var settingRepository = context.RequestServices.GetService(typeof(ISettingRepository)) as ISettingRepository; - return settingRepository.GetSettings(EntityNames.Site, alias.SiteId) + return settingRepository.GetSettings(EntityNames.Site, alias.SiteId, EntityNames.Host, -1) .ToDictionary(setting => setting.SettingName, setting => setting.SettingValue); }); context.Items.Add(Constants.HttpContextSiteSettingsKey, sitesettings); diff --git a/Oqtane.Server/Repository/Interfaces/ISettingRepository.cs b/Oqtane.Server/Repository/Interfaces/ISettingRepository.cs index febb7c5c..3708d4cd 100644 --- a/Oqtane.Server/Repository/Interfaces/ISettingRepository.cs +++ b/Oqtane.Server/Repository/Interfaces/ISettingRepository.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Oqtane.Models; +using Oqtane.Shared; namespace Oqtane.Repository { @@ -7,6 +8,7 @@ namespace Oqtane.Repository { IEnumerable GetSettings(string entityName); IEnumerable GetSettings(string entityName, int entityId); + IEnumerable GetSettings(string entityName1, int entityId1, string entityName2, int entityId2); Setting AddSetting(Setting setting); Setting UpdateSetting(Setting setting); Setting GetSetting(string entityName, int settingId); diff --git a/Oqtane.Server/Repository/SettingRepository.cs b/Oqtane.Server/Repository/SettingRepository.cs index 4fc7c70e..fdf57a13 100644 --- a/Oqtane.Server/Repository/SettingRepository.cs +++ b/Oqtane.Server/Repository/SettingRepository.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Linq; -using System.Linq.Expressions; +using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using Oqtane.Infrastructure; @@ -39,24 +39,27 @@ namespace Oqtane.Repository public IEnumerable GetSettings(string entityName, int entityId) { - var settings = GetSettings(entityName).ToList(); - if (entityName == EntityNames.Site) + return GetSettings(entityName).Where(item => item.EntityId == entityId); + } + + public IEnumerable GetSettings(string entityName1, int entityId1, string entityName2, int entityId2) + { + // merge settings from entity2 into entity1 + var settings1 = GetSettings(entityName1, entityId1).ToList(); + foreach (var setting2 in GetSettings(entityName2, entityId2)) { - // site settings can be overridden by host settings - var hostsettings = GetSettings(EntityNames.Host); - foreach (var hostsetting in hostsettings) + var setting1 = settings1.FirstOrDefault(item => item.SettingName == setting2.SettingName); + if (setting1 == null) { - if (settings.Any(item => item.SettingName == hostsetting.SettingName)) - { - settings.First(item => item.SettingName == hostsetting.SettingName).SettingValue = hostsetting.SettingValue; - } - else - { - settings.Add(new Setting { SettingId = -1, EntityName = entityName, EntityId = entityId, SettingName = hostsetting.SettingName, SettingValue = hostsetting.SettingValue, IsPrivate = hostsetting.IsPrivate }); - } + settings1.Add(new Setting { EntityName = entityName1, EntityId = entityId1, SettingName = setting2.SettingName, SettingValue = setting2.SettingValue, IsPrivate = setting2.IsPrivate }); + } + else + { + setting1.SettingValue = setting2.SettingValue; + setting1.IsPrivate = setting2.IsPrivate; } } - return settings.Where(item => item.EntityId == entityId); + return settings1; } public Setting AddSetting(Setting setting) diff --git a/Oqtane.Server/Services/SiteService.cs b/Oqtane.Server/Services/SiteService.cs index 11c624c3..cc0991d8 100644 --- a/Oqtane.Server/Services/SiteService.cs +++ b/Oqtane.Server/Services/SiteService.cs @@ -111,7 +111,7 @@ namespace Oqtane.Services if (site != null && site.SiteId == alias.SiteId) { // site settings - site.Settings = _settings.GetSettings(EntityNames.Site, site.SiteId) + site.Settings = _settings.GetSettings(EntityNames.Site, site.SiteId, EntityNames.Host, -1) .ToDictionary(setting => setting.SettingName, setting => (setting.IsPrivate ? _private : "") + setting.SettingValue); // populate file extensions From 24b666a382de80b11bbaf807823cbbda6dddd658 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Wed, 30 Apr 2025 13:55:11 -0400 Subject: [PATCH 5/8] remove unecessary using statment --- Oqtane.Server/Repository/SettingRepository.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Oqtane.Server/Repository/SettingRepository.cs b/Oqtane.Server/Repository/SettingRepository.cs index fdf57a13..be40938b 100644 --- a/Oqtane.Server/Repository/SettingRepository.cs +++ b/Oqtane.Server/Repository/SettingRepository.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using Oqtane.Infrastructure; From 6aff27778dd8425d0fe5c6724483c73165f7286b Mon Sep 17 00:00:00 2001 From: sbwalker Date: Wed, 30 Apr 2025 14:18:29 -0400 Subject: [PATCH 6/8] use new GetSettingValue() method --- .../Infrastructure/Jobs/NotificationJob.cs | 39 +++++++------------ 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs b/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs index bfee3066..80f955e6 100644 --- a/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs +++ b/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs @@ -40,27 +40,26 @@ namespace Oqtane.Infrastructure log += "Processing Notifications For Site: " + site.Name + "
"; // get site settings - List sitesettings = settingRepository.GetSettings(EntityNames.Site, site.SiteId, EntityNames.Host, -1).ToList(); - Dictionary settings = GetSettings(sitesettings); - if (!site.IsDeleted && (!settings.ContainsKey("SMTPEnabled") || settings["SMTPEnabled"] == "True")) + List settings = settingRepository.GetSettings(EntityNames.Site, site.SiteId, EntityNames.Host, -1).ToList(); + + if (!site.IsDeleted && settingRepository.GetSettingValue(settings, "SMTPEnabled", "True") == "True") { - if (settings.ContainsKey("SMTPHost") && settings["SMTPHost"] != "" && - settings.ContainsKey("SMTPPort") && settings["SMTPPort"] != "" && - settings.ContainsKey("SMTPSSL") && settings["SMTPSSL"] != "" && - settings.ContainsKey("SMTPSender") && settings["SMTPSender"] != "") + if (settingRepository.GetSettingValue(settings, "SMTPHost", "") != "" && + settingRepository.GetSettingValue(settings, "SMTPPort", "") != "" && + settingRepository.GetSettingValue(settings, "SMTPSender", "") != "") { // construct SMTP Client var client = new SmtpClient() { DeliveryMethod = SmtpDeliveryMethod.Network, UseDefaultCredentials = false, - Host = settings["SMTPHost"], - Port = int.Parse(settings["SMTPPort"]), - EnableSsl = bool.Parse(settings["SMTPSSL"]) + Host = settingRepository.GetSettingValue(settings, "SMTPHost", ""), + Port = int.Parse(settingRepository.GetSettingValue(settings, "SMTPPort", "")), + EnableSsl = bool.Parse(settingRepository.GetSettingValue(settings, "SMTPSSL", "False")) }; - if (settings["SMTPUsername"] != "" && settings["SMTPPassword"] != "") + if (settingRepository.GetSettingValue(settings, "SMTPUsername", "") != "" && settingRepository.GetSettingValue(settings, "SMTPPassword", "") != "") { - client.Credentials = new NetworkCredential(settings["SMTPUsername"], settings["SMTPPassword"]); + client.Credentials = new NetworkCredential(settingRepository.GetSettingValue(settings, "SMTPUsername", ""), settingRepository.GetSettingValue(settings, "SMTPPassword", "")); } // iterate through undelivered notifications @@ -100,7 +99,7 @@ namespace Oqtane.Infrastructure MailMessage mailMessage = new MailMessage(); // sender - if (settings.ContainsKey("SMTPRelay") && settings["SMTPRelay"] == "True" && !string.IsNullOrEmpty(notification.FromEmail)) + if (settingRepository.GetSettingValue(settings, "SMTPRelay", "False") == "True" && !string.IsNullOrEmpty(notification.FromEmail)) { if (!string.IsNullOrEmpty(notification.FromDisplayName)) { @@ -113,7 +112,7 @@ namespace Oqtane.Infrastructure } else { - mailMessage.From = new MailAddress(settings["SMTPSender"], (!string.IsNullOrEmpty(notification.FromDisplayName)) ? notification.FromDisplayName : site.Name); + mailMessage.From = new MailAddress(settingRepository.GetSettingValue(settings, "SMTPSender", ""), (!string.IsNullOrEmpty(notification.FromDisplayName)) ? notification.FromDisplayName : site.Name); } // recipient @@ -162,7 +161,7 @@ namespace Oqtane.Infrastructure } else { - log += "SMTP Not Configured Properly In Site Settings - Host, Port, SSL, And Sender Are All Required" + "
"; + log += "SMTP Not Configured Properly In Site Settings - Host, Port, And Sender Are All Required" + "
"; } } else @@ -173,15 +172,5 @@ namespace Oqtane.Infrastructure return log; } - - private Dictionary GetSettings(List settings) - { - Dictionary dictionary = new Dictionary(); - foreach (Setting setting in settings.OrderBy(item => item.SettingName).ToList()) - { - dictionary.Add(setting.SettingName, setting.SettingValue); - } - return dictionary; - } } } From da1e859fda48165d134f5f136647ff6434e82b4d Mon Sep 17 00:00:00 2001 From: sbwalker Date: Wed, 30 Apr 2025 14:34:54 -0400 Subject: [PATCH 7/8] use new GetSettingValue() method --- .../Infrastructure/Jobs/NotificationJob.cs | 2 +- Oqtane.Server/Infrastructure/Jobs/PurgeJob.cs | 37 +++---------------- .../Interfaces/ISettingRepository.cs | 2 +- Oqtane.Server/Repository/SettingRepository.cs | 2 +- 4 files changed, 8 insertions(+), 35 deletions(-) diff --git a/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs b/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs index 80f955e6..4147455b 100644 --- a/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs +++ b/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs @@ -40,7 +40,7 @@ namespace Oqtane.Infrastructure log += "Processing Notifications For Site: " + site.Name + "
"; // get site settings - List settings = settingRepository.GetSettings(EntityNames.Site, site.SiteId, EntityNames.Host, -1).ToList(); + var settings = settingRepository.GetSettings(EntityNames.Site, site.SiteId, EntityNames.Host, -1); if (!site.IsDeleted && settingRepository.GetSettingValue(settings, "SMTPEnabled", "True") == "True") { diff --git a/Oqtane.Server/Infrastructure/Jobs/PurgeJob.cs b/Oqtane.Server/Infrastructure/Jobs/PurgeJob.cs index 5cf4c59c..89a2238d 100644 --- a/Oqtane.Server/Infrastructure/Jobs/PurgeJob.cs +++ b/Oqtane.Server/Infrastructure/Jobs/PurgeJob.cs @@ -40,18 +40,13 @@ namespace Oqtane.Infrastructure foreach (Site site in sites) { log += "
Processing Site: " + site.Name + "
"; - int retention; int count; // get site settings - Dictionary settings = GetSettings(settingRepository.GetSettings(EntityNames.Site, site.SiteId).ToList()); + var settings = settingRepository.GetSettings(EntityNames.Site, site.SiteId, EntityNames.Host, -1); // purge event log - retention = 30; // 30 days - if (settings.ContainsKey("LogRetention") && !string.IsNullOrEmpty(settings["LogRetention"])) - { - retention = int.Parse(settings["LogRetention"]); - } + var retention = int.Parse(settingRepository.GetSettingValue(settings, "LogRetention", "30")); // 30 day default try { count = logRepository.DeleteLogs(site.SiteId, retention); @@ -65,11 +60,7 @@ namespace Oqtane.Infrastructure // purge visitors if (site.VisitorTracking) { - retention = 30; // 30 days - if (settings.ContainsKey("VisitorRetention") && !string.IsNullOrEmpty(settings["VisitorRetention"])) - { - retention = int.Parse(settings["VisitorRetention"]); - } + retention = int.Parse(settingRepository.GetSettingValue(settings, "VisitorRetention", "30")); // 30 day default try { count = visitorRepository.DeleteVisitors(site.SiteId, retention); @@ -82,11 +73,7 @@ namespace Oqtane.Infrastructure } // purge notifications - retention = 30; // 30 days - if (settings.ContainsKey("NotificationRetention") && !string.IsNullOrEmpty(settings["NotificationRetention"])) - { - retention = int.Parse(settings["NotificationRetention"]); - } + retention = int.Parse(settingRepository.GetSettingValue(settings, "NotificationRetention", "30")); // 30 day default try { count = notificationRepository.DeleteNotifications(site.SiteId, retention); @@ -98,11 +85,7 @@ namespace Oqtane.Infrastructure } // purge broken urls - retention = 30; // 30 days - if (settings.ContainsKey("UrlMappingRetention") && !string.IsNullOrEmpty(settings["UrlMappingRetention"])) - { - retention = int.Parse(settings["UrlMappingRetention"]); - } + retention = int.Parse(settingRepository.GetSettingValue(settings, "UrlMappingRetention", "30")); // 30 day default try { count = urlMappingRepository.DeleteUrlMappings(site.SiteId, retention); @@ -127,15 +110,5 @@ namespace Oqtane.Infrastructure return log; } - - private Dictionary GetSettings(List settings) - { - Dictionary dictionary = new Dictionary(); - foreach (Setting setting in settings.OrderBy(item => item.SettingName).ToList()) - { - dictionary.Add(setting.SettingName, setting.SettingValue); - } - return dictionary; - } } } diff --git a/Oqtane.Server/Repository/Interfaces/ISettingRepository.cs b/Oqtane.Server/Repository/Interfaces/ISettingRepository.cs index 3708d4cd..e74e8eda 100644 --- a/Oqtane.Server/Repository/Interfaces/ISettingRepository.cs +++ b/Oqtane.Server/Repository/Interfaces/ISettingRepository.cs @@ -15,6 +15,6 @@ namespace Oqtane.Repository Setting GetSetting(string entityName, int entityId, string settingName); void DeleteSetting(string entityName, int settingId); void DeleteSettings(string entityName, int entityId); - string GetSettingValue(List settings, string settingName, string defaultValue); + string GetSettingValue(IEnumerable settings, string settingName, string defaultValue); } } diff --git a/Oqtane.Server/Repository/SettingRepository.cs b/Oqtane.Server/Repository/SettingRepository.cs index be40938b..735ec981 100644 --- a/Oqtane.Server/Repository/SettingRepository.cs +++ b/Oqtane.Server/Repository/SettingRepository.cs @@ -167,7 +167,7 @@ namespace Oqtane.Repository ManageCache(entityName); } - public string GetSettingValue(List settings, string settingName, string defaultValue) + public string GetSettingValue(IEnumerable settings, string settingName, string defaultValue) { var setting = settings.FirstOrDefault(item => item.SettingName == settingName); if (setting != null) From 6f60a91f4cd72b437d9018476b9e3b5bd0bbee87 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Thu, 1 May 2025 23:32:37 -0400 Subject: [PATCH 8/8] add new Register Url and Profile Url options to User Management / Settings --- Oqtane.Client/Modules/Admin/Users/Index.razor | 57 +++++++++++-------- .../Resources/Modules/Admin/Users/Index.resx | 14 ++++- .../Themes/Controls/Theme/UserProfile.razor | 27 +++++++-- 3 files changed, 69 insertions(+), 29 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Users/Index.razor b/Oqtane.Client/Modules/Admin/Users/Index.razor index a73350f0..d3eb9bc7 100644 --- a/Oqtane.Client/Modules/Admin/Users/Index.razor +++ b/Oqtane.Client/Modules/Admin/Users/Index.razor @@ -59,29 +59,23 @@ else + @if (_allowregistration == "true") + { +
+ +
+ +
+
+ } +
+ +
+ +
+
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) { - @if (_providertype != "") - { -
- -
- -
-
- } - else - { -
- -
- -
-
- }
@@ -432,6 +426,15 @@ else
+
+ +
+ +
+
} } @@ -485,7 +488,8 @@ else private List users; private string _allowregistration; - private string _allowsitelogin; + private string _registerurl; + private string _profileurl; private string _twofactor; private string _cookiename; private string _cookieexpiration; @@ -533,6 +537,7 @@ else private string _createusers; private string _verifyusers; private string _allowhostrole; + private string _allowsitelogin; private string _secret; private string _secrettype = "password"; @@ -553,7 +558,8 @@ else var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); _allowregistration = PageState.Site.AllowRegistration.ToString().ToLower(); - _allowsitelogin = SettingService.GetSetting(settings, "LoginOptions:AllowSiteLogin", "true"); + _registerurl = SettingService.GetSetting(settings, "LoginOptions:RegisterUrl", ""); + _profileurl = SettingService.GetSetting(settings, "LoginOptions:ProfileUrl", ""); if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) { @@ -616,6 +622,7 @@ else _createusers = SettingService.GetSetting(settings, "ExternalLogin:CreateUsers", "true"); _verifyusers = SettingService.GetSetting(settings, "ExternalLogin:VerifyUsers", "true"); _allowhostrole = SettingService.GetSetting(settings, "ExternalLogin:AllowHostRole", "false"); + _allowsitelogin = SettingService.GetSetting(settings, "LoginOptions:AllowSiteLogin", "true"); } private async Task LoadUsersAsync(bool load) @@ -673,10 +680,11 @@ else await SiteService.UpdateSiteAsync(site); var settings = await SettingService.GetSiteSettingsAsync(site.SiteId); - settings = SettingService.SetSetting(settings, "LoginOptions:AllowSiteLogin", _allowsitelogin, false); if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) { + settings = SettingService.SetSetting(settings, "LoginOptions:RegisterUrl", _registerurl, false); + settings = SettingService.SetSetting(settings, "LoginOptions:ProfileUrl", _profileurl, false); settings = SettingService.SetSetting(settings, "LoginOptions:TwoFactor", _twofactor, false); settings = SettingService.SetSetting(settings, "LoginOptions:CookieName", _cookiename, true); settings = SettingService.SetSetting(settings, "LoginOptions:CookieExpiration", _cookieexpiration, true); @@ -720,6 +728,7 @@ else settings = SettingService.SetSetting(settings, "ExternalLogin:CreateUsers", _createusers, true); settings = SettingService.SetSetting(settings, "ExternalLogin:VerifyUsers", _verifyusers, true); settings = SettingService.SetSetting(settings, "ExternalLogin:AllowHostRole", _allowhostrole, true); + settings = SettingService.SetSetting(settings, "LoginOptions:AllowSiteLogin", _allowsitelogin, false); settings = SettingService.SetSetting(settings, "JwtOptions:Secret", _secret, true); settings = SettingService.SetSetting(settings, "JwtOptions:Issuer", _issuer, true); diff --git a/Oqtane.Client/Resources/Modules/Admin/Users/Index.resx b/Oqtane.Client/Resources/Modules/Admin/Users/Index.resx index a0a7c1f4..c48ec4fa 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Users/Index.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Users/Index.resx @@ -132,6 +132,18 @@ Allow Registration? + + Optionally provide a custom registration url + + + Register Url: + + + Optionally provide a custom user profile url + + + Profile Url: + Error Saving Settings @@ -208,7 +220,7 @@ Do you want to allow users to sign in using a username and password that is managed locally on this site? Note that you should only disable this option if you have already sucessfully configured an external login provider, or else you may lock yourself out of the site. - Allow Login? + Allow Local Login? The authority url or issuer url associated with the identity provider diff --git a/Oqtane.Client/Themes/Controls/Theme/UserProfile.razor b/Oqtane.Client/Themes/Controls/Theme/UserProfile.razor index d408b2ae..e99eada5 100644 --- a/Oqtane.Client/Themes/Controls/Theme/UserProfile.razor +++ b/Oqtane.Client/Themes/Controls/Theme/UserProfile.razor @@ -1,6 +1,7 @@ @namespace Oqtane.Themes.Controls @using System.Net @inherits ThemeControlBase +@inject ISettingService SettingService @inject IStringLocalizer Localizer @inject NavigationManager NavigationManager @@ -51,20 +52,38 @@ if (!string.IsNullOrEmpty(RegisterUrl)) { - _registerurl = RegisterUrl + "?returnurl=" + (RegisterUrl.Contains("://") ? WebUtility.UrlEncode(PageState.Route.RootUrl) + _returnurl : _returnurl); + _registerurl = RegisterUrl; + _registerurl += (!_registerurl.Contains("?") ? "?" : "&") + "returnurl=" + (_registerurl.Contains("://") ? WebUtility.UrlEncode(PageState.Route.RootUrl) + _returnurl : _returnurl); } else { - _registerurl = NavigateUrl("register", "returnurl=" + _returnurl); + if (!string.IsNullOrEmpty(SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:RegisterUrl", ""))) + { + _registerurl = SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:RegisterUrl", ""); + _registerurl += (!_registerurl.Contains("?") ? "?" : "&") + "returnurl=" + (_registerurl.Contains("://") ? WebUtility.UrlEncode(PageState.Route.RootUrl) + _returnurl : _returnurl); + } + else + { + _registerurl = NavigateUrl("register", "returnurl=" + _returnurl); + } } if (!string.IsNullOrEmpty(ProfileUrl)) { - _profileurl = ProfileUrl + "?returnurl=" + (ProfileUrl.Contains("://") ? WebUtility.UrlEncode(PageState.Route.RootUrl) + _returnurl : _returnurl); + _profileurl = ProfileUrl; + _profileurl += (!_profileurl.Contains("?") ? "?" : "&") + "returnurl=" + (_profileurl.Contains("://") ? WebUtility.UrlEncode(PageState.Route.RootUrl) + _returnurl : _returnurl); } else { - _profileurl = NavigateUrl("profile", "returnurl=" + _returnurl); + if (!string.IsNullOrEmpty(SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:ProfileUrl", ""))) + { + _profileurl = SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:ProfileUrl", ""); + _profileurl += (!_profileurl.Contains("?") ? "?" : "&") + "returnurl=" + (_profileurl.Contains("://") ? WebUtility.UrlEncode(PageState.Route.RootUrl) + _returnurl : _returnurl); + } + else + { + _profileurl = NavigateUrl("profile", "returnurl=" + _returnurl); + } } } }