This commit is contained in:
Shaun Walker 2022-03-30 22:08:32 -04:00
parent 8ddaf57e17
commit a70f1ee1e0
12 changed files with 134 additions and 94 deletions

View File

@ -95,9 +95,9 @@
{ {
_togglepassword = Localizer["ShowPassword"]; _togglepassword = Localizer["ShowPassword"];
if (PageState.Site.Settings.ContainsKey("ExternalLogin:AllowSiteLogin") && !string.IsNullOrEmpty(PageState.Site.Settings["ExternalLogin:AllowSiteLogin"])) if (PageState.Site.Settings.ContainsKey("LoginOptions:AllowSiteLogin") && !string.IsNullOrEmpty(PageState.Site.Settings["LoginOptions:AllowSiteLogin"]))
{ {
_allowsitelogin = bool.Parse(PageState.Site.Settings["ExternalLogin:AllowSiteLogin"]); _allowsitelogin = bool.Parse(PageState.Site.Settings["LoginOptions:AllowSiteLogin"]);
} }
if (PageState.Site.Settings.ContainsKey("ExternalLogin:ProviderType") && !string.IsNullOrEmpty(PageState.Site.Settings["ExternalLogin:ProviderType"])) if (PageState.Site.Settings.ContainsKey("ExternalLogin:ProviderType") && !string.IsNullOrEmpty(PageState.Site.Settings["ExternalLogin:ProviderType"]))

View File

@ -41,15 +41,18 @@ else
<input id="confirm" type="password" class="form-control" @bind="@confirm" autocomplete="new-password" /> <input id="confirm" type="password" class="form-control" @bind="@confirm" autocomplete="new-password" />
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center"> @if (allowtwofactor)
<Label Class="col-sm-3" For="twofactor" HelpText="Indicates if you are using two factor authentication. Two factor authentication requires you to enter a verification code sent via email after you sign in." ResourceKey="TwoFactor"></Label> {
<div class="col-sm-9"> <div class="row mb-1 align-items-center">
<select id="twofactor" class="form-select" @bind="@twofactor" required> <Label Class="col-sm-3" For="twofactor" HelpText="Indicates if you are using two factor authentication. Two factor authentication requires you to enter a verification code sent via email after you sign in." ResourceKey="TwoFactor"></Label>
<option value="True">@SharedLocalizer["Yes"]</option> <div class="col-sm-9">
<option value="False">@SharedLocalizer["No"]</option> <select id="twofactor" class="form-select" @bind="@twofactor" required>
</select> <option value="True">@SharedLocalizer["Yes"]</option>
</div> <option value="False">@SharedLocalizer["No"]</option>
</div> </select>
</div>
</div>
}
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="email" HelpText="Your email address where you wish to receive notifications" ResourceKey="Email"></Label> <Label Class="col-sm-3" For="email" HelpText="Your email address where you wish to receive notifications" ResourceKey="Email"></Label>
<div class="col-sm-9"> <div class="col-sm-9">
@ -216,6 +219,7 @@ else
private string username = string.Empty; private string username = string.Empty;
private string password = string.Empty; private string password = string.Empty;
private string confirm = string.Empty; private string confirm = string.Empty;
private bool allowtwofactor = false;
private string twofactor = "False"; private string twofactor = "False";
private string email = string.Empty; private string email = string.Empty;
private string displayname = string.Empty; private string displayname = string.Empty;
@ -235,6 +239,11 @@ else
{ {
try try
{ {
if (PageState.Site.Settings.ContainsKey("LoginOptions:TwoFactor") && !string.IsNullOrEmpty(PageState.Site.Settings["LoginOptions:TwoFactor"]))
{
allowtwofactor = bool.Parse(PageState.Site.Settings["LoginOptions:TwoFactor"]);
}
if (PageState.User != null) if (PageState.User != null)
{ {
username = PageState.User.Username; username = PageState.User.Username;

View File

@ -55,16 +55,56 @@ else
</TabPanel> </TabPanel>
<TabPanel Name="Settings" Heading="Settings" ResourceKey="Settings"> <TabPanel Name="Settings" Heading="Settings" ResourceKey="Settings">
<div class="container"> <div class="container">
<div class="row mb-1 align-items-center"> <Section Name="User" Heading="User Settings" ResourceKey="UserSettings">
<Label Class="col-sm-3" For="allowregistration" HelpText="Do You Want To Allow Visitors To Be Able To Register For A User Account On This Site?" ResourceKey="AllowRegistration">Allow User Registration?</Label> <div class="row mb-1 align-items-center">
<div class="col-sm-9"> <Label Class="col-sm-3" For="allowregistration" HelpText="Do you want anonymous visitors to be able to register for an account on the site" ResourceKey="AllowRegistration">Allow User Registration?</Label>
<select id="allowregistration" class="form-select" @bind="@_allowregistration" required> <div class="col-sm-9">
<option value="True">@SharedLocalizer["Yes"]</option> <select id="allowregistration" class="form-select" @bind="@_allowregistration">
<option value="False">@SharedLocalizer["No"]</option> <option value="True">@SharedLocalizer["Yes"]</option>
</select> <option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div> </div>
</div> @if (_providertype != "")
<br /> {
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="allowsitelogin" HelpText="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." ResourceKey="AllowSiteLogin">Allow Login?</Label>
<div class="col-sm-9">
<select id="allowsitelogin" class="form-select" @bind="@_allowsitelogin">
<option value="true">@SharedLocalizer["Yes"]</option>
<option value="false">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
}
else
{
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="allowsitelogin" HelpText="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." ResourceKey="AllowSiteLogin">Allow Login?</Label>
<div class="col-sm-9">
<input id="allowsitelogin" class="form-control" value="@SharedLocalizer["Yes"]" readonly />
</div>
</div>
}
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="twofactor" HelpText="Do you want to allow users to use two factor authentication? Note that the Notification Job in Scheduled Jobs needs to be enabled for this option to work properly." ResourceKey="TwoFactor">Allow Two Factor?</Label>
<div class="col-sm-9">
<select id="twofactor" class="form-select" @bind="@_twofactor">
<option value="true">@SharedLocalizer["Yes"]</option>
<option value="false">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="cookietype" HelpText="Cookies are usually managed per domain. However you can also choose to have distinct cookies for each site." ResourceKey="CookieType">Cookie Type:</Label>
<div class="col-sm-9">
<select id="cookietype" class="form-select" @bind="@_cookietype">
<option value="domain">@Localizer["Domain"]</option>
<option value="site">@Localizer["Site"]</option>
</select>
</div>
</div>
</Section>
<Section Name="Password" Heading="Password Settings" ResourceKey="PasswordSettings"> <Section Name="Password" Heading="Password Settings" ResourceKey="PasswordSettings">
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="minimumlength" HelpText="The Minimum Length For A Password" ResourceKey="RequiredLength">Minimum Length:</Label> <Label Class="col-sm-3" For="minimumlength" HelpText="The Minimum Length For A Password" ResourceKey="RequiredLength">Minimum Length:</Label>
@ -129,17 +169,6 @@ else
</div> </div>
</div> </div>
</Section> </Section>
<Section Name="Cookie" Heading="Cookie Settings" ResourceKey="CookieSettings">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="cookietype" HelpText="Cookies are usually managed per domain. However you can also choose to have distinct cookies for each site." ResourceKey="CookieType">Cookie Type:</Label>
<div class="col-sm-9">
<select id="cookietype" class="form-select" @bind="@_cookietype">
<option value="domain">@Localizer["Domain"]</option>
<option value="site">@Localizer["Site"]</option>
</select>
</div>
</div>
</Section>
<Section Name="ExternalLogin" Heading="External Login Settings" ResourceKey="ExternalLoginSettings"> <Section Name="ExternalLogin" Heading="External Login Settings" ResourceKey="ExternalLoginSettings">
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="providertype" HelpText="Select the external login provider type" ResourceKey="ProviderType">Provider Type:</Label> <Label Class="col-sm-3" For="providertype" HelpText="Select the external login provider type" ResourceKey="ProviderType">Provider Type:</Label>
@ -255,15 +284,6 @@ else
</select> </select>
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="allowsitelogin" HelpText="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." ResourceKey="AllowSiteLogin">Allow Site Login?</Label>
<div class="col-sm-9">
<select id="allowsitelogin" class="form-select" @bind="@_allowsitelogin">
<option value="true">@SharedLocalizer["Yes"]</option>
<option value="false">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
} }
</Section> </Section>
<Section Name="Token" Heading="Token Settings" ResourceKey="TokenSettings"> <Section Name="Token" Heading="Token Settings" ResourceKey="TokenSettings">
@ -314,6 +334,10 @@ else
private string _search; private string _search;
private string _allowregistration; private string _allowregistration;
private string _allowsitelogin;
private string _twofactor;
private string _cookietype;
private string _minimumlength; private string _minimumlength;
private string _uniquecharacters; private string _uniquecharacters;
private string _requiredigit; private string _requiredigit;
@ -323,8 +347,6 @@ else
private string _maximumfailures; private string _maximumfailures;
private string _lockoutduration; private string _lockoutduration;
private string _cookietype;
private string _providertype; private string _providertype;
private string _providername; private string _providername;
private string _authority; private string _authority;
@ -340,7 +362,6 @@ else
private string _emailclaimtype; private string _emailclaimtype;
private string _domainfilter; private string _domainfilter;
private string _createusers; private string _createusers;
private string _allowsitelogin;
private string _secret; private string _secret;
private string _issuer; private string _issuer;
@ -356,8 +377,11 @@ else
await LoadSettingsAsync(); await LoadSettingsAsync();
userroles = Search(_search); userroles = Search(_search);
_allowregistration = PageState.Site.AllowRegistration.ToString();
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
_allowregistration = PageState.Site.AllowRegistration.ToString();
_allowsitelogin = SettingService.GetSetting(settings, "LoginOptions:AllowSiteLogin", "true");
_twofactor = SettingService.GetSetting(settings, "LoginOptions:TwoFactor", "false");
_cookietype = SettingService.GetSetting(settings, "LoginOptions:CookieType", "domain");
_minimumlength = SettingService.GetSetting(settings, "IdentityOptions:Password:RequiredLength", "6"); _minimumlength = SettingService.GetSetting(settings, "IdentityOptions:Password:RequiredLength", "6");
_uniquecharacters = SettingService.GetSetting(settings, "IdentityOptions:Password:RequiredUniqueChars", "1"); _uniquecharacters = SettingService.GetSetting(settings, "IdentityOptions:Password:RequiredUniqueChars", "1");
@ -369,8 +393,6 @@ else
_maximumfailures = SettingService.GetSetting(settings, "IdentityOptions:Lockout:MaxFailedAccessAttempts", "5"); _maximumfailures = SettingService.GetSetting(settings, "IdentityOptions:Lockout:MaxFailedAccessAttempts", "5");
_lockoutduration = TimeSpan.Parse(SettingService.GetSetting(settings, "IdentityOptions:Lockout:DefaultLockoutTimeSpan", "00:05:00")).TotalMinutes.ToString(); _lockoutduration = TimeSpan.Parse(SettingService.GetSetting(settings, "IdentityOptions:Lockout:DefaultLockoutTimeSpan", "00:05:00")).TotalMinutes.ToString();
_cookietype = SettingService.GetSetting(settings, "CookieOptions:CookieType", "domain");
_providertype = SettingService.GetSetting(settings, "ExternalLogin:ProviderType", ""); _providertype = SettingService.GetSetting(settings, "ExternalLogin:ProviderType", "");
_providername = SettingService.GetSetting(settings, "ExternalLogin:ProviderName", ""); _providername = SettingService.GetSetting(settings, "ExternalLogin:ProviderName", "");
_authority = SettingService.GetSetting(settings, "ExternalLogin:Authority", ""); _authority = SettingService.GetSetting(settings, "ExternalLogin:Authority", "");
@ -386,7 +408,6 @@ else
_emailclaimtype = SettingService.GetSetting(settings, "ExternalLogin:EmailClaimType", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"); _emailclaimtype = SettingService.GetSetting(settings, "ExternalLogin:EmailClaimType", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress");
_domainfilter = SettingService.GetSetting(settings, "ExternalLogin:DomainFilter", ""); _domainfilter = SettingService.GetSetting(settings, "ExternalLogin:DomainFilter", "");
_createusers = SettingService.GetSetting(settings, "ExternalLogin:CreateUsers", "true"); _createusers = SettingService.GetSetting(settings, "ExternalLogin:CreateUsers", "true");
_allowsitelogin = SettingService.GetSetting(settings, "ExternalLogin:AllowSiteLogin", "true");
_secret = SettingService.GetSetting(settings, "JwtOptions:Secret", ""); _secret = SettingService.GetSetting(settings, "JwtOptions:Secret", "");
_issuer = SettingService.GetSetting(settings, "JwtOptions:Issuer", PageState.Uri.Scheme + "://" + PageState.Alias.Name); _issuer = SettingService.GetSetting(settings, "JwtOptions:Issuer", PageState.Uri.Scheme + "://" + PageState.Alias.Name);
@ -462,6 +483,10 @@ else
await SiteService.UpdateSiteAsync(site); await SiteService.UpdateSiteAsync(site);
var settings = await SettingService.GetSiteSettingsAsync(site.SiteId); var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
settings = SettingService.SetSetting(settings, "LoginOptions:AllowSiteLogin", _allowsitelogin, false);
settings = SettingService.SetSetting(settings, "LoginOptions:TwoFactor", _twofactor, false);
settings = SettingService.SetSetting(settings, "LoginOptions:CookieType", _cookietype, true);
settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequiredLength", _minimumlength, true); settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequiredLength", _minimumlength, true);
settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequiredUniqueChars", _uniquecharacters, true); settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequiredUniqueChars", _uniquecharacters, true);
settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequireDigit", _requiredigit, true); settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequireDigit", _requiredigit, true);
@ -472,8 +497,6 @@ else
settings = SettingService.SetSetting(settings, "IdentityOptions:Lockout:MaxFailedAccessAttempts", _maximumfailures, true); settings = SettingService.SetSetting(settings, "IdentityOptions:Lockout:MaxFailedAccessAttempts", _maximumfailures, true);
settings = SettingService.SetSetting(settings, "IdentityOptions:Lockout:DefaultLockoutTimeSpan", TimeSpan.FromMinutes(Convert.ToInt64(_lockoutduration)).ToString(), true); settings = SettingService.SetSetting(settings, "IdentityOptions:Lockout:DefaultLockoutTimeSpan", TimeSpan.FromMinutes(Convert.ToInt64(_lockoutduration)).ToString(), true);
settings = SettingService.SetSetting(settings, "CookieOptions:CookieType", _cookietype, true);
settings = SettingService.SetSetting(settings, "ExternalLogin:ProviderType", _providertype, false); settings = SettingService.SetSetting(settings, "ExternalLogin:ProviderType", _providertype, false);
settings = SettingService.SetSetting(settings, "ExternalLogin:ProviderName", _providername, false); settings = SettingService.SetSetting(settings, "ExternalLogin:ProviderName", _providername, false);
settings = SettingService.SetSetting(settings, "ExternalLogin:Authority", _authority, true); settings = SettingService.SetSetting(settings, "ExternalLogin:Authority", _authority, true);
@ -488,7 +511,6 @@ else
settings = SettingService.SetSetting(settings, "ExternalLogin:EmailClaimType", _emailclaimtype, true); settings = SettingService.SetSetting(settings, "ExternalLogin:EmailClaimType", _emailclaimtype, true);
settings = SettingService.SetSetting(settings, "ExternalLogin:DomainFilter", _domainfilter, true); settings = SettingService.SetSetting(settings, "ExternalLogin:DomainFilter", _domainfilter, true);
settings = SettingService.SetSetting(settings, "ExternalLogin:CreateUsers", _createusers, true); settings = SettingService.SetSetting(settings, "ExternalLogin:CreateUsers", _createusers, true);
settings = SettingService.SetSetting(settings, "ExternalLogin:AllowSiteLogin", _allowsitelogin, false);
if (!string.IsNullOrEmpty(_secret) && _secret.Length < 16) _secret = (_secret + "????????????????").Substring(0, 16); if (!string.IsNullOrEmpty(_secret) && _secret.Length < 16) _secret = (_secret + "????????????????").Substring(0, 16);
settings = SettingService.SetSetting(settings, "JwtOptions:Secret", _secret, true); settings = SettingService.SetSetting(settings, "JwtOptions:Secret", _secret, true);
@ -497,7 +519,7 @@ else
settings = SettingService.SetSetting(settings, "JwtOptions:Lifetime", _lifetime, true); settings = SettingService.SetSetting(settings, "JwtOptions:Lifetime", _lifetime, true);
await SettingService.UpdateSiteSettingsAsync(settings, site.SiteId); await SettingService.UpdateSiteSettingsAsync(settings, site.SiteId);
await SettingService.ClearSiteSettingsCacheAsync(site.SiteId); await SettingService.ClearSiteSettingsCacheAsync();
AddModuleMessage(Localizer["Success.SaveSiteSettings"], MessageType.Success); AddModuleMessage(Localizer["Success.SaveSiteSettings"], MessageType.Success);
} }

View File

@ -28,9 +28,9 @@ namespace Oqtane.Client
var builder = WebAssemblyHostBuilder.CreateDefault(args); var builder = WebAssemblyHostBuilder.CreateDefault(args);
var httpClient = new HttpClient {BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)}; var httpClient = new HttpClient {BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)};
builder.Services.AddSingleton(httpClient);
builder.Services.AddHttpClient(); // IHttpClientFactory for calling remote services via RemoteServiceBase
builder.Services.AddSingleton(httpClient);
builder.Services.AddHttpClient("Remote");
builder.Services.AddOptions(); builder.Services.AddOptions();
// Register localization services // Register localization services

View File

@ -208,7 +208,7 @@
<value>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.</value> <value>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.</value>
</data> </data>
<data name="AllowSiteLogin.Text" xml:space="preserve"> <data name="AllowSiteLogin.Text" xml:space="preserve">
<value>Allow Site Login?</value> <value>Allow Login?</value>
</data> </data>
<data name="Authority.HelpText" xml:space="preserve"> <data name="Authority.HelpText" xml:space="preserve">
<value>The Authority Url or Issuer Url associated with the OpenID Connect provider</value> <value>The Authority Url or Issuer Url associated with the OpenID Connect provider</value>
@ -315,14 +315,14 @@
<data name="Audience.Text" xml:space="preserve"> <data name="Audience.Text" xml:space="preserve">
<value>Audience:</value> <value>Audience:</value>
</data> </data>
<data name="CookieSettings.Heading" xml:space="preserve"> <data name="UserSettings.Heading" xml:space="preserve">
<value>Cookie Settings</value> <value>User Settings</value>
</data> </data>
<data name="CookieType.HelpText" xml:space="preserve"> <data name="CookieType.HelpText" xml:space="preserve">
<value>Cookies are usually managed per domain. However you can also choose to have distinct cookies for each site.</value> <value>Login cookies are usually managed per domain. However you can also choose to have distinct cookies for each site.</value>
</data> </data>
<data name="CookieType.Text" xml:space="preserve"> <data name="CookieType.Text" xml:space="preserve">
<value>Cookie Type:</value> <value>Login Cookie Type:</value>
</data> </data>
<data name="CreateToken" xml:space="preserve"> <data name="CreateToken" xml:space="preserve">
<value>Create Token</value> <value>Create Token</value>
@ -354,4 +354,10 @@
<data name="TokenSettings.Heading" xml:space="preserve"> <data name="TokenSettings.Heading" xml:space="preserve">
<value>Token Settings</value> <value>Token Settings</value>
</data> </data>
<data name="TwoFactor.HelpText" xml:space="preserve">
<value>Do you want to allow users to use two factor authentication? Note that the Notification Job in Scheduled Jobs needs to be enabled and your SMTP options need to be configured in Site Settings for this option to work properly.</value>
</data>
<data name="TwoFactor.Text" xml:space="preserve">
<value>Allow Two Factor?</value>
</data>
</root> </root>

View File

@ -42,7 +42,7 @@ namespace Oqtane.Services
/// Clears site option cache /// Clears site option cache
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
Task ClearSiteSettingsCacheAsync(int siteId); Task ClearSiteSettingsCacheAsync();
/// <summary> /// <summary>
/// Returns a key-value dictionary of all page settings for the given page /// Returns a key-value dictionary of all page settings for the given page

View File

@ -42,9 +42,9 @@ namespace Oqtane.Services
await UpdateSettingsAsync(siteSettings, EntityNames.Site, siteId); await UpdateSettingsAsync(siteSettings, EntityNames.Site, siteId);
} }
public async Task ClearSiteSettingsCacheAsync(int siteId) public async Task ClearSiteSettingsCacheAsync()
{ {
await DeleteAsync($"{Apiurl}/clear/{siteId}"); await DeleteAsync($"{Apiurl}/clear");
} }
public async Task<Dictionary<string, string>> GetPageSettingsAsync(int pageId) public async Task<Dictionary<string, string>> GetPageSettingsAsync(int pageId)

View File

@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authentication.OAuth; using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.Extensions.Options;
namespace Oqtane.Controllers namespace Oqtane.Controllers
{ {
@ -23,18 +24,26 @@ namespace Oqtane.Controllers
private readonly IPageModuleRepository _pageModules; private readonly IPageModuleRepository _pageModules;
private readonly IUserPermissions _userPermissions; private readonly IUserPermissions _userPermissions;
private readonly ISyncManager _syncManager; private readonly ISyncManager _syncManager;
private readonly IAliasAccessor _aliasAccessor;
private readonly IOptionsMonitorCache<CookieAuthenticationOptions> _cookieCache;
private readonly IOptionsMonitorCache<OpenIdConnectOptions> _oidcCache;
private readonly IOptionsMonitorCache<OAuthOptions> _oauthCache;
private readonly IOptionsMonitorCache<IdentityOptions> _identityCache;
private readonly ILogManager _logger; private readonly ILogManager _logger;
private readonly Alias _alias; private readonly Alias _alias;
private readonly IAliasAccessor _aliasAccessor;
private readonly string _visitorCookie; private readonly string _visitorCookie;
public SettingController(ISettingRepository settings, IPageModuleRepository pageModules, IUserPermissions userPermissions, ITenantManager tenantManager, ISyncManager syncManager, IAliasAccessor aliasAccessor, ILogManager logger) public SettingController(ISettingRepository settings, IPageModuleRepository pageModules, IUserPermissions userPermissions, ITenantManager tenantManager, ISyncManager syncManager, IAliasAccessor aliasAccessor, IOptionsMonitorCache<CookieAuthenticationOptions> cookieCache, IOptionsMonitorCache<OpenIdConnectOptions> oidcCache, IOptionsMonitorCache<OAuthOptions> oauthCache, IOptionsMonitorCache<IdentityOptions> identityCache, ILogManager logger)
{ {
_settings = settings; _settings = settings;
_pageModules = pageModules; _pageModules = pageModules;
_userPermissions = userPermissions; _userPermissions = userPermissions;
_syncManager = syncManager; _syncManager = syncManager;
_aliasAccessor = aliasAccessor; _aliasAccessor = aliasAccessor;
_cookieCache = cookieCache;
_oidcCache = oidcCache;
_oauthCache = oauthCache;
_identityCache = identityCache;
_logger = logger; _logger = logger;
_alias = tenantManager.GetAlias(); _alias = tenantManager.GetAlias();
_visitorCookie = "APP_VISITOR_" + _alias.SiteId.ToString(); _visitorCookie = "APP_VISITOR_" + _alias.SiteId.ToString();
@ -139,18 +148,26 @@ namespace Oqtane.Controllers
} }
// DELETE api/<controller>/clear // DELETE api/<controller>/clear
[HttpDelete("clear/{id}")] [HttpDelete("clear")]
[Authorize(Roles = RoleNames.Admin)] [Authorize(Roles = RoleNames.Admin)]
public void Clear(int id) public void Clear()
{ {
var cookieAuthenticationOptionsCache = new SiteOptionsCache<CookieAuthenticationOptions>(_aliasAccessor); // clear SiteOptionsCache for each option type
cookieAuthenticationOptionsCache.Clear(); var cookieCache = new SiteOptionsCache<CookieAuthenticationOptions>(_aliasAccessor);
var openIdConnectOptionsCache = new SiteOptionsCache<OpenIdConnectOptions>(_aliasAccessor); cookieCache.Clear();
openIdConnectOptionsCache.Clear(); var oidcCache = new SiteOptionsCache<OpenIdConnectOptions>(_aliasAccessor);
var oAuthOptionsCache = new SiteOptionsCache<OAuthOptions>(_aliasAccessor); oidcCache.Clear();
oAuthOptionsCache.Clear(); var oauthCache = new SiteOptionsCache<OAuthOptions>(_aliasAccessor);
var identityOptionsCache = new SiteOptionsCache<IdentityOptions>(_aliasAccessor); oauthCache.Clear();
identityOptionsCache.Clear(); var identityCache = new SiteOptionsCache<IdentityOptions>(_aliasAccessor);
identityCache.Clear();
// clear IOptionsMonitorCache for each option type
_cookieCache.Clear();
_oidcCache.Clear();
_oauthCache.Clear();
_identityCache.Clear();
_logger.Log(LogLevel.Information, this, LogFunction.Other, "Site Options Cache Cleared"); _logger.Log(LogLevel.Information, this, LogFunction.Other, "Site Options Cache Cleared");
} }

View File

@ -28,7 +28,7 @@ namespace Oqtane.Extensions
// site cookie authentication options // site cookie authentication options
builder.AddSiteOptions<CookieAuthenticationOptions>((options, alias, sitesettings) => builder.AddSiteOptions<CookieAuthenticationOptions>((options, alias, sitesettings) =>
{ {
if (sitesettings.GetValue("CookieOptions:CookieType", "domain") == "domain") if (sitesettings.GetValue("LoginOptions:CookieType", "domain") == "domain")
{ {
options.Cookie.Name = ".AspNetCore.Identity.Application"; options.Cookie.Name = ".AspNetCore.Identity.Application";
} }

View File

@ -36,7 +36,7 @@ namespace Oqtane.Infrastructure
var user = jwtManager.ValidateToken(token, secret, sitesettings.GetValue("JwtOptions:Issuer", ""), sitesettings.GetValue("JwtOptions:Audience", "")); var user = jwtManager.ValidateToken(token, secret, sitesettings.GetValue("JwtOptions:Issuer", ""), sitesettings.GetValue("JwtOptions:Audience", ""));
if (user != null) if (user != null)
{ {
// populate principal (reload user roles to ensure most accurate permission assigments) // populate principal (reload user roles to ensure most accurate permissions)
var _userRoles = context.RequestServices.GetService(typeof(IUserRoleRepository)) as IUserRoleRepository; var _userRoles = context.RequestServices.GetService(typeof(IUserRoleRepository)) as IUserRoleRepository;
var principal = (ClaimsIdentity)context.User.Identity; var principal = (ClaimsIdentity)context.User.Identity;
UserSecurity.ResetClaimsIdentity(principal); UserSecurity.ResetClaimsIdentity(principal);
@ -52,7 +52,8 @@ namespace Oqtane.Infrastructure
} }
} }
await _next(context); // continue processing
if (_next != null) await _next(context);
} }
} }
} }

View File

@ -9,11 +9,11 @@ namespace Oqtane.Infrastructure
{ {
internal class TenantMiddleware internal class TenantMiddleware
{ {
private readonly RequestDelegate next; private readonly RequestDelegate _next;
public TenantMiddleware(RequestDelegate next) public TenantMiddleware(RequestDelegate next)
{ {
this.next = next; _next = next;
} }
public async Task Invoke(HttpContext context) public async Task Invoke(HttpContext context)
@ -55,7 +55,7 @@ namespace Oqtane.Infrastructure
} }
// continue processing // continue processing
if (next != null) await next(context); if (_next != null) await _next(context);
} }
} }
} }

View File

@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Oqtane.Models;
namespace Oqtane.Infrastructure namespace Oqtane.Infrastructure
{ {
@ -20,21 +19,7 @@ namespace Oqtane.Infrastructure
{ {
var cache = map.GetOrAdd(GetKey(), new OptionsCache<TOptions>()); var cache = map.GetOrAdd(GetKey(), new OptionsCache<TOptions>());
cache.Clear(); cache.Clear();
}
public void Clear(Alias alias)
{
var cache = map.GetOrAdd(alias.SiteKey, new OptionsCache<TOptions>());
cache.Clear();
}
public void ClearAll()
{
foreach (var cache in map.Values)
{
cache.Clear();
}
} }
public TOptions GetOrAdd(string name, Func<TOptions> createOptions) public TOptions GetOrAdd(string name, Func<TOptions> createOptions)