From 70a3fab1ff04f9825c1bd8494f58be28975ddea1 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Mon, 10 Mar 2025 10:53:05 -0400 Subject: [PATCH] added Logout Everywhere option to User Settings --- Oqtane.Client/Modules/Admin/Users/Index.razor | 658 +++++++++--------- .../Resources/Modules/Admin/Users/Index.resx | 6 + .../Theme/ControlPanelInteractive.razor | 2 +- .../Themes/Controls/Theme/Login.razor | 1 + .../Themes/Controls/Theme/LoginBase.cs | 5 +- 5 files changed, 346 insertions(+), 326 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Users/Index.razor b/Oqtane.Client/Modules/Admin/Users/Index.razor index 8af3d381..e0d895c8 100644 --- a/Oqtane.Client/Modules/Admin/Users/Index.razor +++ b/Oqtane.Client/Modules/Admin/Users/Index.razor @@ -17,171 +17,180 @@ else { -   +   -
-   -   -   +
+   +   +   @Localizer["Username"] @Localizer["Name"] @Localizer["Email"] @Localizer["LastLoginOn"] -
- - +
+ + - - + + - - + + - - @context.User.Username - @context.User.DisplayName - @((MarkupString)string.Format("{1}", @context.User.Email, @context.User.Email)) - @((context.User.LastLoginOn != DateTime.MinValue) ? string.Format("{0:dd-MMM-yyyy HH:mm:ss}", context.User.LastLoginOn) : "") - -
+ + @context.User.Username + @context.User.DisplayName + @((MarkupString)string.Format("{1}", @context.User.Email, @context.User.Email)) + @((context.User.LastLoginOn != DateTime.MinValue) ? string.Format("{0:dd-MMM-yyyy HH:mm:ss}", context.User.LastLoginOn) : "") + +
-
-
-
- -
- -
-
- @if (_providertype != "") - { -
- -
- -
-
- } - else - { -
- -
- -
-
- } - @if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) - { -
- -
- -
-
-
- -
- -
-
-
+
+
+
+ +
+ +
+
+ @if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) + { + @if (_providertype != "") + { +
+ +
+ +
+
+ } + else + { +
+ +
+ +
+
+ } +
+ +
+ +
+
+
+ +
+ +
+
+
-
- -
-
-
+
+ +
+
+
-
+
-
-
- } -
- @if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) - { -
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
-
-
- -
- -
-
-
- -
- -
-
-
-
+ + + +
+
+
+ +
+ +
+
+ } +
+ @if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) + { +
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
@@ -201,77 +210,77 @@ else
- -
- - - - -
-
- @if (_providertype != "") - { -
- -
- -
-
- } - @if (_providertype == AuthenticationProviderTypes.OpenIDConnect) - { -
- -
- -
-
-
- -
- -
-
- } - @if (_providertype == AuthenticationProviderTypes.OAuth2) - { -
- -
- -
-
-
- -
- -
-
-
- -
- -
-
- } - @if (_providertype != "") - { -
- -
- -
-
-
- -
-
- - -
-
-
+ + + +
+ + @if (_providertype != "") + { +
+ +
+ +
+
+ } + @if (_providertype == AuthenticationProviderTypes.OpenIDConnect) + { +
+ +
+ +
+
+
+ +
+ +
+
+ } + @if (_providertype == AuthenticationProviderTypes.OAuth2) + { +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ } + @if (_providertype != "") + { +
+ +
+ +
+
+
+ +
+
+ + +
+
+
@if (_providertype == AuthenticationProviderTypes.OpenIDConnect) {
@@ -291,32 +300,32 @@ else
}
- -
- -
-
-
- -
- -
-
+ +
+ +
+
- -
- -
-
-
- -
- -
-
+ +
+ +
+ +
+ +
+ +
+
+
+ +
+ +
+
@@ -334,10 +343,10 @@ else
-
- -
-
+
+ +
+
@@ -346,16 +355,16 @@ else
-
- -
-
-
- -
- -
-
+
+ +
+
+
+ +
+ +
+
@@ -374,11 +383,11 @@ else
- -
- -
-
+ +
+ +
+
@@ -389,20 +398,20 @@ else
- -
- -
-
-
- -
- -
-
+ +
+ +
+ +
+ +
+ +
+
@@ -413,51 +422,51 @@ else
} - -
-
- -
-
- - -
-
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
-
- - -
-
-
-
- } - -
- + +
+
+ +
+
+ + +
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+
+ + +
+
+
+
+ } + +
+
-
+ } @code { @@ -469,6 +478,7 @@ else private string _cookiename; private string _cookieexpiration; private string _alwaysremember; + private string _logouteverywhere; private string _minimumlength; private string _uniquecharacters; @@ -529,7 +539,7 @@ else await LoadUsersAsync(true); var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); - _allowregistration = PageState.Site.AllowRegistration.ToString(); + _allowregistration = PageState.Site.AllowRegistration.ToString().ToLower(); _allowsitelogin = SettingService.GetSetting(settings, "LoginOptions:AllowSiteLogin", "true"); if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) @@ -538,6 +548,7 @@ else _cookiename = SettingService.GetSetting(settings, "LoginOptions:CookieName", ".AspNetCore.Identity.Application"); _cookieexpiration = SettingService.GetSetting(settings, "LoginOptions:CookieExpiration", ""); _alwaysremember = SettingService.GetSetting(settings, "LoginOptions:AlwaysRemember", "false"); + _logouteverywhere = SettingService.GetSetting(settings, "LoginOptions:LogoutEverywhere", "false"); _minimumlength = SettingService.GetSetting(settings, "IdentityOptions:Password:RequiredLength", "6"); _uniquecharacters = SettingService.GetSetting(settings, "IdentityOptions:Password:RequiredUniqueChars", "1"); @@ -656,6 +667,7 @@ else settings = SettingService.SetSetting(settings, "LoginOptions:CookieName", _cookiename, true); settings = SettingService.SetSetting(settings, "LoginOptions:CookieExpiration", _cookieexpiration, true); settings = SettingService.SetSetting(settings, "LoginOptions:AlwaysRemember", _alwaysremember, false); + settings = SettingService.SetSetting(settings, "LoginOptions:LogoutEverywhere", _logouteverywhere, false); settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequiredLength", _minimumlength, true); settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequiredUniqueChars", _uniquecharacters, true); diff --git a/Oqtane.Client/Resources/Modules/Admin/Users/Index.resx b/Oqtane.Client/Resources/Modules/Admin/Users/Index.resx index 34884fb5..3b0bda17 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Users/Index.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Users/Index.resx @@ -507,4 +507,10 @@ Error Deleting User + + Logout Everywhere? + + + Do you want users to be logged out of every active session on any device, or only their current session? + \ No newline at end of file diff --git a/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor b/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor index 5f1f5d5d..5dd940f8 100644 --- a/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor +++ b/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor @@ -573,7 +573,7 @@ else { // post to the Logout page to complete the logout process - var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, returnurl = url }; + var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, returnurl = url, everywhere = bool.Parse(SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:LogoutEverywhere", "false")) }; var interop = new Interop(jsRuntime); await interop.SubmitForm(Utilities.TenantUrl(PageState.Alias, "/pages/logout/"), fields); } diff --git a/Oqtane.Client/Themes/Controls/Theme/Login.razor b/Oqtane.Client/Themes/Controls/Theme/Login.razor index 69bd2922..f1bf1ebc 100644 --- a/Oqtane.Client/Themes/Controls/Theme/Login.razor +++ b/Oqtane.Client/Themes/Controls/Theme/Login.razor @@ -15,6 +15,7 @@
+
} diff --git a/Oqtane.Client/Themes/Controls/Theme/LoginBase.cs b/Oqtane.Client/Themes/Controls/Theme/LoginBase.cs index 099be1d5..846cbcb7 100644 --- a/Oqtane.Client/Themes/Controls/Theme/LoginBase.cs +++ b/Oqtane.Client/Themes/Controls/Theme/LoginBase.cs @@ -4,7 +4,6 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Components; using Microsoft.JSInterop; using Oqtane.Enums; -using Oqtane.Models; using Oqtane.Providers; using Oqtane.Security; using Oqtane.Services; @@ -26,6 +25,7 @@ namespace Oqtane.Themes.Controls protected string loginurl; protected string logouturl; protected string returnurl; + protected string everywhere; protected override void OnParametersSet() { @@ -57,6 +57,7 @@ namespace Oqtane.Themes.Controls // set logout url logouturl = Utilities.TenantUrl(PageState.Alias, "/pages/logout/"); + everywhere = SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:LogoutEverywhere", "false"); // verify anonymous users can access current page if (UserSecurity.IsAuthorized(null, PermissionNames.View, PageState.Page.PermissionList) && Utilities.IsEffectiveAndNotExpired(PageState.Page.EffectiveDate, PageState.Page.ExpiryDate)) @@ -98,7 +99,7 @@ namespace Oqtane.Themes.Controls else // this condition is only valid for legacy Login button inheriting from LoginBase { // post to the Logout page to complete the logout process - var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, returnurl = returnurl }; + var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, returnurl = returnurl, everywhere = bool.Parse(SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:LogoutEverywhere", "false")) }; var interop = new Interop(jsRuntime); await interop.SubmitForm(logouturl, fields); }