diff --git a/src/Umbraco.Core/Composing/TypeFinderConfig.cs b/src/Umbraco.Core/Composing/TypeFinderConfig.cs index 8e63958a06..adb82e5336 100644 --- a/src/Umbraco.Core/Composing/TypeFinderConfig.cs +++ b/src/Umbraco.Core/Composing/TypeFinderConfig.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Configuration.UmbracoSettings; diff --git a/src/Umbraco.Core/Events/UserNotificationsHandler.cs b/src/Umbraco.Core/Events/UserNotificationsHandler.cs index 45be01ce65..d626df7dab 100644 --- a/src/Umbraco.Core/Events/UserNotificationsHandler.cs +++ b/src/Umbraco.Core/Events/UserNotificationsHandler.cs @@ -124,7 +124,7 @@ namespace Umbraco.Cms.Core.Events private readonly INotificationService _notificationService; private readonly IUserService _userService; private readonly ILocalizedTextService _textService; - private readonly GlobalSettings _globalSettings; + private GlobalSettings _globalSettings; private readonly ILogger _logger; /// @@ -136,7 +136,7 @@ namespace Umbraco.Cms.Core.Events INotificationService notificationService, IUserService userService, ILocalizedTextService textService, - IOptions globalSettings, + IOptionsMonitor globalSettings, ILogger logger) { _backOfficeSecurityAccessor = backOfficeSecurityAccessor; @@ -144,8 +144,10 @@ namespace Umbraco.Cms.Core.Events _notificationService = notificationService; _userService = userService; _textService = textService; - _globalSettings = globalSettings.Value; + _globalSettings = globalSettings.CurrentValue; _logger = logger; + + globalSettings.OnChange(x => _globalSettings = x); } public void Notify(IAction action, params IContent[] entities) diff --git a/src/Umbraco.Core/Handlers/AuditNotificationsHandler.cs b/src/Umbraco.Core/Handlers/AuditNotificationsHandler.cs index ed7fdb971f..e22bf86a59 100644 --- a/src/Umbraco.Core/Handlers/AuditNotificationsHandler.cs +++ b/src/Umbraco.Core/Handlers/AuditNotificationsHandler.cs @@ -38,7 +38,7 @@ namespace Umbraco.Cms.Core.Handlers IUserService userService, IEntityService entityService, IIpResolver ipResolver, - IOptions globalSettings, + IOptionsMonitor globalSettings, IBackOfficeSecurityAccessor backOfficeSecurityAccessor, IMemberService memberService) { @@ -48,7 +48,7 @@ namespace Umbraco.Cms.Core.Handlers _ipResolver = ipResolver; _backOfficeSecurityAccessor = backOfficeSecurityAccessor; _memberService = memberService; - _globalSettings = globalSettings.Value; + _globalSettings = globalSettings.CurrentValue; } private IUser CurrentPerformingUser diff --git a/src/Umbraco.Core/HealthChecks/NotificationMethods/EmailNotificationMethod.cs b/src/Umbraco.Core/HealthChecks/NotificationMethods/EmailNotificationMethod.cs index 8de4cd8cc3..de6df973e3 100644 --- a/src/Umbraco.Core/HealthChecks/NotificationMethods/EmailNotificationMethod.cs +++ b/src/Umbraco.Core/HealthChecks/NotificationMethods/EmailNotificationMethod.cs @@ -17,15 +17,14 @@ namespace Umbraco.Cms.Core.HealthChecks.NotificationMethods private readonly IHostingEnvironment _hostingEnvironment; private readonly IEmailSender _emailSender; private readonly IMarkdownToHtmlConverter _markdownToHtmlConverter; - - private readonly ContentSettings _contentSettings; + private ContentSettings _contentSettings; public EmailNotificationMethod( ILocalizedTextService textService, IHostingEnvironment hostingEnvironment, IEmailSender emailSender, - IOptions healthChecksSettings, - IOptions contentSettings, + IOptionsMonitor healthChecksSettings, + IOptionsMonitor contentSettings, IMarkdownToHtmlConverter markdownToHtmlConverter) : base(healthChecksSettings) { @@ -42,7 +41,9 @@ namespace Umbraco.Cms.Core.HealthChecks.NotificationMethods _hostingEnvironment = hostingEnvironment; _emailSender = emailSender; _markdownToHtmlConverter = markdownToHtmlConverter; - _contentSettings = contentSettings.Value ?? throw new ArgumentNullException(nameof(contentSettings)); + _contentSettings = contentSettings.CurrentValue ?? throw new ArgumentNullException(nameof(contentSettings)); + + contentSettings.OnChange(x => _contentSettings = x); } public string RecipientEmail { get; } diff --git a/src/Umbraco.Core/HealthChecks/NotificationMethods/NotificationMethodBase.cs b/src/Umbraco.Core/HealthChecks/NotificationMethods/NotificationMethodBase.cs index 10af1de106..3a889154d2 100644 --- a/src/Umbraco.Core/HealthChecks/NotificationMethods/NotificationMethodBase.cs +++ b/src/Umbraco.Core/HealthChecks/NotificationMethods/NotificationMethodBase.cs @@ -8,7 +8,7 @@ namespace Umbraco.Cms.Core.HealthChecks.NotificationMethods { public abstract class NotificationMethodBase : IHealthCheckNotificationMethod { - protected NotificationMethodBase(IOptions healthCheckSettings) + protected NotificationMethodBase(IOptionsMonitor healthCheckSettings) { var type = GetType(); var attribute = type.GetCustomAttribute(); @@ -18,7 +18,7 @@ namespace Umbraco.Cms.Core.HealthChecks.NotificationMethods return; } - var notificationMethods = healthCheckSettings.Value.Notification.NotificationMethods; + var notificationMethods = healthCheckSettings.CurrentValue.Notification.NotificationMethods; if (!notificationMethods.TryGetValue(attribute.Alias, out var notificationMethod)) { Enabled = false; diff --git a/src/Umbraco.Core/Models/ContentEditing/UserInvite.cs b/src/Umbraco.Core/Models/ContentEditing/UserInvite.cs index 6eb5c12ddf..6db43e99ae 100644 --- a/src/Umbraco.Core/Models/ContentEditing/UserInvite.cs +++ b/src/Umbraco.Core/Models/ContentEditing/UserInvite.cs @@ -35,7 +35,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing if (UserGroups.Any() == false) yield return new ValidationResult("A user must be assigned to at least one group", new[] { nameof(UserGroups) }); - var securitySettings = validationContext.GetRequiredService>(); + var securitySettings = validationContext.GetRequiredService>(); if (securitySettings.Value.UsernameIsEmail == false && Username.IsNullOrWhiteSpace()) yield return new ValidationResult("A username cannot be empty", new[] { nameof(Username) }); diff --git a/src/Umbraco.Core/PublishedCache/DefaultCultureAccessor.cs b/src/Umbraco.Core/PublishedCache/DefaultCultureAccessor.cs index 145206daf1..648041a3a4 100644 --- a/src/Umbraco.Core/PublishedCache/DefaultCultureAccessor.cs +++ b/src/Umbraco.Core/PublishedCache/DefaultCultureAccessor.cs @@ -11,23 +11,23 @@ namespace Umbraco.Cms.Core.PublishedCache { private readonly ILocalizationService _localizationService; private readonly IRuntimeState _runtimeState; - private readonly IOptions _options; + private GlobalSettings _options; /// /// Initializes a new instance of the class. /// - public DefaultCultureAccessor(ILocalizationService localizationService, IRuntimeState runtimeState, IOptions options) + public DefaultCultureAccessor(ILocalizationService localizationService, IRuntimeState runtimeState, IOptionsMonitor options) { _localizationService = localizationService; _runtimeState = runtimeState; - _options = options; - + _options = options.CurrentValue; + options.OnChange(x => _options = x); } /// public string DefaultCulture => _runtimeState.Level == RuntimeLevel.Run ? _localizationService.GetDefaultLanguageIsoCode() ?? "" // fast - : _options.Value.DefaultUILanguage; // default for install and upgrade, when the service is n/a + : _options.DefaultUILanguage; // default for install and upgrade, when the service is n/a } } diff --git a/src/Umbraco.Core/Routing/AliasUrlProvider.cs b/src/Umbraco.Core/Routing/AliasUrlProvider.cs index 54d246219e..6f6181da21 100644 --- a/src/Umbraco.Core/Routing/AliasUrlProvider.cs +++ b/src/Umbraco.Core/Routing/AliasUrlProvider.cs @@ -14,19 +14,21 @@ namespace Umbraco.Cms.Core.Routing /// public class AliasUrlProvider : IUrlProvider { - private readonly RequestHandlerSettings _requestConfig; + private RequestHandlerSettings _requestConfig; private readonly ISiteDomainMapper _siteDomainMapper; private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly UriUtility _uriUtility; private readonly IPublishedValueFallback _publishedValueFallback; - public AliasUrlProvider(IOptions requestConfig, ISiteDomainMapper siteDomainMapper, UriUtility uriUtility, IPublishedValueFallback publishedValueFallback, IUmbracoContextAccessor umbracoContextAccessor) + public AliasUrlProvider(IOptionsMonitor requestConfig, ISiteDomainMapper siteDomainMapper, UriUtility uriUtility, IPublishedValueFallback publishedValueFallback, IUmbracoContextAccessor umbracoContextAccessor) { - _requestConfig = requestConfig.Value; + _requestConfig = requestConfig.CurrentValue; _siteDomainMapper = siteDomainMapper; _uriUtility = uriUtility; _publishedValueFallback = publishedValueFallback; _umbracoContextAccessor = umbracoContextAccessor; + + requestConfig.OnChange(x => _requestConfig = x); } // note - at the moment we seem to accept pretty much anything as an alias diff --git a/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs b/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs index d8093aed1b..1ff54c1546 100644 --- a/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs +++ b/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs @@ -18,21 +18,23 @@ namespace Umbraco.Cms.Core.Routing private readonly ILogger _logger; private readonly IRequestAccessor _requestAccessor; private readonly IUmbracoContextAccessor _umbracoContextAccessor; - private readonly WebRoutingSettings _webRoutingSettings; + private WebRoutingSettings _webRoutingSettings; /// /// Initializes a new instance of the class. /// public ContentFinderByIdPath( - IOptions webRoutingSettings, + IOptionsMonitor webRoutingSettings, ILogger logger, IRequestAccessor requestAccessor, IUmbracoContextAccessor umbracoContextAccessor) { - _webRoutingSettings = webRoutingSettings.Value ?? throw new System.ArgumentNullException(nameof(webRoutingSettings)); + _webRoutingSettings = webRoutingSettings.CurrentValue ?? throw new System.ArgumentNullException(nameof(webRoutingSettings)); _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); _requestAccessor = requestAccessor ?? throw new System.ArgumentNullException(nameof(requestAccessor)); _umbracoContextAccessor = umbracoContextAccessor ?? throw new System.ArgumentNullException(nameof(umbracoContextAccessor)); + + webRoutingSettings.OnChange(x => _webRoutingSettings = x); } /// diff --git a/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs b/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs index 2e5515fef2..f8eb328eed 100644 --- a/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs +++ b/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs @@ -23,7 +23,7 @@ namespace Umbraco.Cms.Core.Routing private readonly IFileService _fileService; private readonly IContentTypeService _contentTypeService; - private readonly WebRoutingSettings _webRoutingSettings; + private WebRoutingSettings _webRoutingSettings; /// /// Initializes a new instance of the class. @@ -33,13 +33,14 @@ namespace Umbraco.Cms.Core.Routing IFileService fileService, IContentTypeService contentTypeService, IUmbracoContextAccessor umbracoContextAccessor, - IOptions webRoutingSettings) + IOptionsMonitor webRoutingSettings) : base(logger, umbracoContextAccessor) { _logger = logger; _fileService = fileService; _contentTypeService = contentTypeService; - _webRoutingSettings = webRoutingSettings.Value; + _webRoutingSettings = webRoutingSettings.CurrentValue; + webRoutingSettings.OnChange(x => _webRoutingSettings = x); } /// diff --git a/src/Umbraco.Core/Routing/DefaultUrlProvider.cs b/src/Umbraco.Core/Routing/DefaultUrlProvider.cs index 16248854e5..969e5bf98b 100644 --- a/src/Umbraco.Core/Routing/DefaultUrlProvider.cs +++ b/src/Umbraco.Core/Routing/DefaultUrlProvider.cs @@ -15,19 +15,20 @@ namespace Umbraco.Cms.Core.Routing /// public class DefaultUrlProvider : IUrlProvider { - private readonly RequestHandlerSettings _requestSettings; + private RequestHandlerSettings _requestSettings; private readonly ILogger _logger; private readonly ISiteDomainMapper _siteDomainMapper; private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly UriUtility _uriUtility; - public DefaultUrlProvider(IOptions requestSettings, ILogger logger, ISiteDomainMapper siteDomainMapper, IUmbracoContextAccessor umbracoContextAccessor, UriUtility uriUtility) + public DefaultUrlProvider(IOptionsMonitor requestSettings, ILogger logger, ISiteDomainMapper siteDomainMapper, IUmbracoContextAccessor umbracoContextAccessor, UriUtility uriUtility) { - _requestSettings = requestSettings.Value; + _requestSettings = requestSettings.CurrentValue; _logger = logger; _siteDomainMapper = siteDomainMapper; _uriUtility = uriUtility; _umbracoContextAccessor = umbracoContextAccessor; + requestSettings.OnChange(x => _requestSettings = x); } #region GetUrl diff --git a/src/Umbraco.Core/Routing/PublishedRouter.cs b/src/Umbraco.Core/Routing/PublishedRouter.cs index 548387a675..f069adffeb 100644 --- a/src/Umbraco.Core/Routing/PublishedRouter.cs +++ b/src/Umbraco.Core/Routing/PublishedRouter.cs @@ -24,7 +24,7 @@ namespace Umbraco.Cms.Core.Routing /// public class PublishedRouter : IPublishedRouter { - private readonly WebRoutingSettings _webRoutingSettings; + private WebRoutingSettings _webRoutingSettings; private readonly ContentFinderCollection _contentFinders; private readonly IContentLastChanceFinder _contentLastChanceFinder; private readonly IProfilingLogger _profilingLogger; @@ -42,7 +42,7 @@ namespace Umbraco.Cms.Core.Routing /// Initializes a new instance of the class. /// public PublishedRouter( - IOptions webRoutingSettings, + IOptionsMonitor webRoutingSettings, ContentFinderCollection contentFinders, IContentLastChanceFinder contentLastChanceFinder, IVariationContextAccessor variationContextAccessor, @@ -56,7 +56,7 @@ namespace Umbraco.Cms.Core.Routing IUmbracoContextAccessor umbracoContextAccessor, IEventAggregator eventAggregator) { - _webRoutingSettings = webRoutingSettings.Value ?? throw new ArgumentNullException(nameof(webRoutingSettings)); + _webRoutingSettings = webRoutingSettings.CurrentValue ?? throw new ArgumentNullException(nameof(webRoutingSettings)); _contentFinders = contentFinders ?? throw new ArgumentNullException(nameof(contentFinders)); _contentLastChanceFinder = contentLastChanceFinder ?? throw new ArgumentNullException(nameof(contentLastChanceFinder)); _profilingLogger = proflog ?? throw new ArgumentNullException(nameof(proflog)); @@ -69,6 +69,7 @@ namespace Umbraco.Cms.Core.Routing _contentTypeService = contentTypeService; _umbracoContextAccessor = umbracoContextAccessor; _eventAggregator = eventAggregator; + webRoutingSettings.OnChange(x => _webRoutingSettings = x); } /// @@ -237,7 +238,7 @@ namespace Umbraco.Cms.Core.Routing // re-route await RouteRequestInternalAsync(builder); - + // return if we are redirect if (builder.IsRedirect()) { diff --git a/src/Umbraco.Core/Routing/UrlProvider.cs b/src/Umbraco.Core/Routing/UrlProvider.cs index 018343d02a..5d43dedc3d 100644 --- a/src/Umbraco.Core/Routing/UrlProvider.cs +++ b/src/Umbraco.Core/Routing/UrlProvider.cs @@ -32,6 +32,7 @@ namespace Umbraco.Cms.Core.Routing _mediaUrlProviders = mediaUrlProviders; _variationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor)); Mode = routingSettings.Value.UrlProviderMode; + } private readonly IUmbracoContextAccessor _umbracoContextAccessor; @@ -122,7 +123,7 @@ namespace Umbraco.Cms.Core.Routing var umbracoContext = _umbracoContextAccessor.GetRequiredUmbracoContext(); current = umbracoContext.CleanedUmbracoUrl; } - + var url = _urlProviders.Select(provider => provider.GetUrl(content, mode, culture, current)) .FirstOrDefault(u => u != null); @@ -230,7 +231,7 @@ namespace Umbraco.Cms.Core.Routing var umbracoContext = _umbracoContextAccessor.GetRequiredUmbracoContext(); current = umbracoContext.CleanedUmbracoUrl; } - + var url = _mediaUrlProviders.Select(provider => provider.GetMediaUrl(content, propertyAlias, mode, culture, current)) diff --git a/src/Umbraco.Core/Templates/HtmlUrlParser.cs b/src/Umbraco.Core/Templates/HtmlUrlParser.cs index 50dc937466..e28aca9ed5 100644 --- a/src/Umbraco.Core/Templates/HtmlUrlParser.cs +++ b/src/Umbraco.Core/Templates/HtmlUrlParser.cs @@ -9,7 +9,7 @@ namespace Umbraco.Cms.Core.Templates { public sealed class HtmlUrlParser { - private readonly ContentSettings _contentSettings; + private ContentSettings _contentSettings; private readonly ILogger _logger; private readonly IIOHelper _ioHelper; private readonly IProfilingLogger _profilingLogger; @@ -17,12 +17,14 @@ namespace Umbraco.Cms.Core.Templates private static readonly Regex ResolveUrlPattern = new Regex("(=[\"\']?)(\\W?\\~(?:.(?![\"\']?\\s+(?:\\S+)=|[>\"\']))+.)[\"\']?", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); - public HtmlUrlParser(IOptions contentSettings, ILogger logger, IProfilingLogger profilingLogger, IIOHelper ioHelper) + public HtmlUrlParser(IOptionsMonitor contentSettings, ILogger logger, IProfilingLogger profilingLogger, IIOHelper ioHelper) { - _contentSettings = contentSettings.Value; + _contentSettings = contentSettings.CurrentValue; _logger = logger; _ioHelper = ioHelper; _profilingLogger = profilingLogger; + + contentSettings.OnChange(x => _contentSettings = x); } /// diff --git a/src/Umbraco.Examine.Lucene/DependencyInjection/ConfigureIndexOptions.cs b/src/Umbraco.Examine.Lucene/DependencyInjection/ConfigureIndexOptions.cs index 7d434cbf23..48c9fbb5ff 100644 --- a/src/Umbraco.Examine.Lucene/DependencyInjection/ConfigureIndexOptions.cs +++ b/src/Umbraco.Examine.Lucene/DependencyInjection/ConfigureIndexOptions.cs @@ -16,14 +16,14 @@ namespace Umbraco.Cms.Infrastructure.Examine.DependencyInjection public sealed class ConfigureIndexOptions : IConfigureNamedOptions { private readonly IUmbracoIndexConfig _umbracoIndexConfig; - private readonly IOptions _settings; + private readonly IndexCreatorSettings _settings; public ConfigureIndexOptions( IUmbracoIndexConfig umbracoIndexConfig, IOptions settings) { _umbracoIndexConfig = umbracoIndexConfig; - _settings = settings; + _settings = settings.Value; } public void Configure(string name, LuceneDirectoryIndexOptions options) @@ -50,13 +50,13 @@ namespace Umbraco.Cms.Infrastructure.Examine.DependencyInjection // ensure indexes are unlocked on startup options.UnlockIndex = true; - if (_settings.Value.LuceneDirectoryFactory == LuceneDirectoryFactory.SyncedTempFileSystemDirectoryFactory) + if (_settings.LuceneDirectoryFactory == LuceneDirectoryFactory.SyncedTempFileSystemDirectoryFactory) { // if this directory factory is enabled then a snapshot deletion policy is required options.IndexDeletionPolicy = new SnapshotDeletionPolicy(new KeepOnlyLastCommitDeletionPolicy()); } - - + + } public void Configure(LuceneDirectoryIndexOptions options) diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs index 1ad30c6e8e..89d6f5ee2c 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs @@ -119,7 +119,7 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection builder.Services.AddSingleton(); builder.Services.AddSingleton(factory - => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(factory.GetRequiredService>().Value))); + => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(factory.GetRequiredService>().CurrentValue))); builder.Services.AddSingleton(); builder.Services.AddSingleton(factory => new MigrationBuilder(factory)); @@ -156,7 +156,7 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection builder.Services.AddSingleton( services => new EmailSender( services.GetRequiredService>(), - services.GetRequiredService>(), + services.GetRequiredService>(), services.GetRequiredService(), services.GetService>(), services.GetService>())); diff --git a/src/Umbraco.Infrastructure/HostedServices/HealthCheckNotifier.cs b/src/Umbraco.Infrastructure/HostedServices/HealthCheckNotifier.cs index 6a0828fad3..4b7656d20d 100644 --- a/src/Umbraco.Infrastructure/HostedServices/HealthCheckNotifier.cs +++ b/src/Umbraco.Infrastructure/HostedServices/HealthCheckNotifier.cs @@ -26,7 +26,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices /// public class HealthCheckNotifier : RecurringHostedServiceBase { - private readonly HealthChecksSettings _healthChecksSettings; + private HealthChecksSettings _healthChecksSettings; private readonly HealthCheckCollection _healthChecks; private readonly HealthCheckNotificationMethodCollection _notifications; private readonly IRuntimeState _runtimeState; @@ -50,7 +50,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices /// The profiling logger. /// Parser of crontab expressions. public HealthCheckNotifier( - IOptions healthChecksSettings, + IOptionsMonitor healthChecksSettings, HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications, IRuntimeState runtimeState, @@ -61,10 +61,10 @@ namespace Umbraco.Cms.Infrastructure.HostedServices IProfilingLogger profilingLogger, ICronTabParser cronTabParser) : base( - healthChecksSettings.Value.Notification.Period, - healthChecksSettings.Value.GetNotificationDelay(cronTabParser, DateTime.Now, DefaultDelay)) + healthChecksSettings.CurrentValue.Notification.Period, + healthChecksSettings.CurrentValue.GetNotificationDelay(cronTabParser, DateTime.Now, DefaultDelay)) { - _healthChecksSettings = healthChecksSettings.Value; + _healthChecksSettings = healthChecksSettings.CurrentValue; _healthChecks = healthChecks; _notifications = notifications; _runtimeState = runtimeState; @@ -73,6 +73,12 @@ namespace Umbraco.Cms.Infrastructure.HostedServices _scopeProvider = scopeProvider; _logger = logger; _profilingLogger = profilingLogger; + + healthChecksSettings.OnChange(x => + { + _healthChecksSettings = x; + ChangePeriod(x.Notification.Period); + }); } public override async Task PerformExecuteAsync(object state) diff --git a/src/Umbraco.Infrastructure/HostedServices/KeepAlive.cs b/src/Umbraco.Infrastructure/HostedServices/KeepAlive.cs index b564e7948d..a27e0d9dee 100644 --- a/src/Umbraco.Infrastructure/HostedServices/KeepAlive.cs +++ b/src/Umbraco.Infrastructure/HostedServices/KeepAlive.cs @@ -24,7 +24,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices { private readonly IHostingEnvironment _hostingEnvironment; private readonly IMainDom _mainDom; - private readonly KeepAliveSettings _keepAliveSettings; + private KeepAliveSettings _keepAliveSettings; private readonly ILogger _logger; private readonly IProfilingLogger _profilingLogger; private readonly IServerRoleAccessor _serverRegistrar; @@ -43,7 +43,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices public KeepAlive( IHostingEnvironment hostingEnvironment, IMainDom mainDom, - IOptions keepAliveSettings, + IOptionsMonitor keepAliveSettings, ILogger logger, IProfilingLogger profilingLogger, IServerRoleAccessor serverRegistrar, @@ -52,11 +52,13 @@ namespace Umbraco.Cms.Infrastructure.HostedServices { _hostingEnvironment = hostingEnvironment; _mainDom = mainDom; - _keepAliveSettings = keepAliveSettings.Value; + _keepAliveSettings = keepAliveSettings.CurrentValue; _logger = logger; _profilingLogger = profilingLogger; _serverRegistrar = serverRegistrar; _httpClientFactory = httpClientFactory; + + keepAliveSettings.OnChange(x => _keepAliveSettings = x); } public override async Task PerformExecuteAsync(object state) diff --git a/src/Umbraco.Infrastructure/HostedServices/LogScrubber.cs b/src/Umbraco.Infrastructure/HostedServices/LogScrubber.cs index 27d9c29e8d..7c12ae39ec 100644 --- a/src/Umbraco.Infrastructure/HostedServices/LogScrubber.cs +++ b/src/Umbraco.Infrastructure/HostedServices/LogScrubber.cs @@ -25,7 +25,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices private readonly IMainDom _mainDom; private readonly IServerRoleAccessor _serverRegistrar; private readonly IAuditService _auditService; - private readonly LoggingSettings _settings; + private LoggingSettings _settings; private readonly IProfilingLogger _profilingLogger; private readonly ILogger _logger; private readonly IScopeProvider _scopeProvider; @@ -44,7 +44,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices IMainDom mainDom, IServerRoleAccessor serverRegistrar, IAuditService auditService, - IOptions settings, + IOptionsMonitor settings, IScopeProvider scopeProvider, ILogger logger, IProfilingLogger profilingLogger) @@ -53,10 +53,11 @@ namespace Umbraco.Cms.Infrastructure.HostedServices _mainDom = mainDom; _serverRegistrar = serverRegistrar; _auditService = auditService; - _settings = settings.Value; + _settings = settings.CurrentValue; _scopeProvider = scopeProvider; _logger = logger; _profilingLogger = profilingLogger; + settings.OnChange(x => _settings = x); } public override Task PerformExecuteAsync(object state) diff --git a/src/Umbraco.Infrastructure/HostedServices/RecurringHostedServiceBase.cs b/src/Umbraco.Infrastructure/HostedServices/RecurringHostedServiceBase.cs index 70dcb3a04e..bf189a374c 100644 --- a/src/Umbraco.Infrastructure/HostedServices/RecurringHostedServiceBase.cs +++ b/src/Umbraco.Infrastructure/HostedServices/RecurringHostedServiceBase.cs @@ -21,7 +21,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices /// protected static readonly TimeSpan DefaultDelay = TimeSpan.FromMinutes(3); - private readonly TimeSpan _period; + private TimeSpan _period; private readonly TimeSpan _delay; private Timer _timer; @@ -36,6 +36,12 @@ namespace Umbraco.Cms.Infrastructure.HostedServices _delay = delay; } + /// + /// Change the period between operations. + /// + /// The new period between tasks + protected void ChangePeriod(TimeSpan newPeriod) => _period = newPeriod; + /// public Task StartAsync(CancellationToken cancellationToken) { diff --git a/src/Umbraco.Infrastructure/HostedServices/ReportSiteTask.cs b/src/Umbraco.Infrastructure/HostedServices/ReportSiteTask.cs index 6eab3a60bc..4f02a89439 100644 --- a/src/Umbraco.Infrastructure/HostedServices/ReportSiteTask.cs +++ b/src/Umbraco.Infrastructure/HostedServices/ReportSiteTask.cs @@ -16,19 +16,20 @@ namespace Umbraco.Cms.Infrastructure.HostedServices { private readonly ILogger _logger; private readonly IUmbracoVersion _umbracoVersion; - private readonly IOptions _globalSettings; + private GlobalSettings _globalSettings; private static HttpClient s_httpClient; public ReportSiteTask( ILogger logger, IUmbracoVersion umbracoVersion, - IOptions globalSettings) + IOptionsMonitor globalSettings) : base(TimeSpan.FromDays(1), TimeSpan.FromMinutes(1)) { _logger = logger; _umbracoVersion = umbracoVersion; - _globalSettings = globalSettings; + _globalSettings = globalSettings.CurrentValue; s_httpClient = new HttpClient(); + globalSettings.OnChange(x => _globalSettings = x); } /// @@ -38,7 +39,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices public override async Task PerformExecuteAsync(object state) { // Try & get a value stored in umbracoSettings.config on the backoffice XML element ID attribute - var backofficeIdentifierRaw = _globalSettings.Value.Id; + var backofficeIdentifierRaw = _globalSettings.Id; // Parse as a GUID & verify its a GUID and not some random string // In case of users may have messed or decided to empty the file contents or put in something random diff --git a/src/Umbraco.Infrastructure/HostedServices/ServerRegistration/TouchServerTask.cs b/src/Umbraco.Infrastructure/HostedServices/ServerRegistration/TouchServerTask.cs index 282847963f..f7c80452a2 100644 --- a/src/Umbraco.Infrastructure/HostedServices/ServerRegistration/TouchServerTask.cs +++ b/src/Umbraco.Infrastructure/HostedServices/ServerRegistration/TouchServerTask.cs @@ -22,7 +22,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices.ServerRegistration private readonly IServerRegistrationService _serverRegistrationService; private readonly IHostingEnvironment _hostingEnvironment; private readonly ILogger _logger; - private readonly GlobalSettings _globalSettings; + private GlobalSettings _globalSettings; /// /// Initializes a new instance of the class. @@ -37,14 +37,19 @@ namespace Umbraco.Cms.Infrastructure.HostedServices.ServerRegistration IServerRegistrationService serverRegistrationService, IHostingEnvironment hostingEnvironment, ILogger logger, - IOptions globalSettings) - : base(globalSettings.Value.DatabaseServerRegistrar.WaitTimeBetweenCalls, TimeSpan.FromSeconds(15)) + IOptionsMonitor globalSettings) + : base(globalSettings.CurrentValue.DatabaseServerRegistrar.WaitTimeBetweenCalls, TimeSpan.FromSeconds(15)) { _runtimeState = runtimeState; _serverRegistrationService = serverRegistrationService ?? throw new ArgumentNullException(nameof(serverRegistrationService)); _hostingEnvironment = hostingEnvironment; _logger = logger; - _globalSettings = globalSettings.Value; + _globalSettings = globalSettings.CurrentValue; + globalSettings.OnChange(x => + { + _globalSettings = x; + ChangePeriod(x.DatabaseServerRegistrar.WaitTimeBetweenCalls); + }); } public override Task PerformExecuteAsync(object state) diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/ThreadAbortExceptionEnricher.cs b/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/ThreadAbortExceptionEnricher.cs index 9ea3d0009d..d0de79931b 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/ThreadAbortExceptionEnricher.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/ThreadAbortExceptionEnricher.cs @@ -15,15 +15,16 @@ namespace Umbraco.Cms.Core.Logging.Serilog.Enrichers /// public class ThreadAbortExceptionEnricher : ILogEventEnricher { - private readonly CoreDebugSettings _coreDebugSettings; + private CoreDebugSettings _coreDebugSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly IMarchal _marchal; - public ThreadAbortExceptionEnricher(IOptions coreDebugSettings, IHostingEnvironment hostingEnvironment, IMarchal marchal) + public ThreadAbortExceptionEnricher(IOptionsMonitor coreDebugSettings, IHostingEnvironment hostingEnvironment, IMarchal marchal) { - _coreDebugSettings = coreDebugSettings.Value; + _coreDebugSettings = coreDebugSettings.CurrentValue; _hostingEnvironment = hostingEnvironment; _marchal = marchal; + coreDebugSettings.OnChange(x => _coreDebugSettings = x); } public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) diff --git a/src/Umbraco.Infrastructure/Mail/EmailSender.cs b/src/Umbraco.Infrastructure/Mail/EmailSender.cs index e5fbde2aac..098d690345 100644 --- a/src/Umbraco.Infrastructure/Mail/EmailSender.cs +++ b/src/Umbraco.Infrastructure/Mail/EmailSender.cs @@ -22,27 +22,28 @@ namespace Umbraco.Cms.Infrastructure.Mail { // TODO: This should encapsulate a BackgroundTaskRunner with a queue to send these emails! private readonly IEventAggregator _eventAggregator; - private readonly GlobalSettings _globalSettings; + private GlobalSettings _globalSettings; private readonly bool _notificationHandlerRegistered; private readonly ILogger _logger; public EmailSender( ILogger logger, - IOptions globalSettings, + IOptionsMonitor globalSettings, IEventAggregator eventAggregator) : this(logger, globalSettings, eventAggregator, null, null) { } public EmailSender( ILogger logger, - IOptions globalSettings, + IOptionsMonitor globalSettings, IEventAggregator eventAggregator, INotificationHandler handler1, INotificationAsyncHandler handler2) { _logger = logger; _eventAggregator = eventAggregator; - _globalSettings = globalSettings.Value; + _globalSettings = globalSettings.CurrentValue; _notificationHandlerRegistered = handler1 is not null || handler2 is not null; + globalSettings.OnChange(x => _globalSettings = x); } /// diff --git a/src/Umbraco.Infrastructure/ModelsBuilder/AutoModelsNotificationHandler.cs b/src/Umbraco.Infrastructure/ModelsBuilder/AutoModelsNotificationHandler.cs index 8017cfbf8e..c61de4ada4 100644 --- a/src/Umbraco.Infrastructure/ModelsBuilder/AutoModelsNotificationHandler.cs +++ b/src/Umbraco.Infrastructure/ModelsBuilder/AutoModelsNotificationHandler.cs @@ -33,15 +33,17 @@ namespace Umbraco.Cms.Infrastructure.ModelsBuilder /// /// Initializes a new instance of the class. /// + public AutoModelsNotificationHandler( ILogger logger, - IOptions config, + IOptionsMonitor config, ModelsGenerator modelGenerator, ModelsGenerationError mbErrors, IMainDom mainDom) { _logger = logger; - _config = config.Value ?? throw new ArgumentNullException(nameof(config)); + //We cant use IOptionsSnapshot here, cause this is used in the Core runtime, and that cannot use a scoped service as it has no scope + _config = config.CurrentValue ?? throw new ArgumentNullException(nameof(config)); _modelGenerator = modelGenerator; _mbErrors = mbErrors; _mainDom = mainDom; diff --git a/src/Umbraco.Infrastructure/ModelsBuilder/Building/ModelsGenerator.cs b/src/Umbraco.Infrastructure/ModelsBuilder/Building/ModelsGenerator.cs index ac4780cb7c..930bc163f0 100644 --- a/src/Umbraco.Infrastructure/ModelsBuilder/Building/ModelsGenerator.cs +++ b/src/Umbraco.Infrastructure/ModelsBuilder/Building/ModelsGenerator.cs @@ -10,16 +10,17 @@ namespace Umbraco.Cms.Infrastructure.ModelsBuilder.Building public class ModelsGenerator { private readonly UmbracoServices _umbracoService; - private readonly ModelsBuilderSettings _config; + private ModelsBuilderSettings _config; private readonly OutOfDateModelsStatus _outOfDateModels; private readonly IHostingEnvironment _hostingEnvironment; - public ModelsGenerator(UmbracoServices umbracoService, IOptions config, OutOfDateModelsStatus outOfDateModels, IHostingEnvironment hostingEnvironment) + public ModelsGenerator(UmbracoServices umbracoService, IOptionsMonitor config, OutOfDateModelsStatus outOfDateModels, IHostingEnvironment hostingEnvironment) { _umbracoService = umbracoService; - _config = config.Value; + _config = config.CurrentValue; _outOfDateModels = outOfDateModels; _hostingEnvironment = hostingEnvironment; + config.OnChange(x => _config = x); } public void GenerateModels() diff --git a/src/Umbraco.Infrastructure/ModelsBuilder/ModelsGenerationError.cs b/src/Umbraco.Infrastructure/ModelsBuilder/ModelsGenerationError.cs index 18b28c2bba..15e629f4f0 100644 --- a/src/Umbraco.Infrastructure/ModelsBuilder/ModelsGenerationError.cs +++ b/src/Umbraco.Infrastructure/ModelsBuilder/ModelsGenerationError.cs @@ -10,16 +10,17 @@ namespace Umbraco.Cms.Infrastructure.ModelsBuilder { public sealed class ModelsGenerationError { - private readonly ModelsBuilderSettings _config; + private ModelsBuilderSettings _config; private readonly IHostingEnvironment _hostingEnvironment; /// /// Initializes a new instance of the class. /// - public ModelsGenerationError(IOptions config, IHostingEnvironment hostingEnvironment) + public ModelsGenerationError(IOptionsMonitor config, IHostingEnvironment hostingEnvironment) { - _config = config.Value; + _config = config.CurrentValue; _hostingEnvironment = hostingEnvironment; + config.OnChange(x => _config = x); } public void Clear() diff --git a/src/Umbraco.Infrastructure/ModelsBuilder/OutOfDateModelsStatus.cs b/src/Umbraco.Infrastructure/ModelsBuilder/OutOfDateModelsStatus.cs index 3816db52bf..1d9ea7d499 100644 --- a/src/Umbraco.Infrastructure/ModelsBuilder/OutOfDateModelsStatus.cs +++ b/src/Umbraco.Infrastructure/ModelsBuilder/OutOfDateModelsStatus.cs @@ -15,16 +15,17 @@ namespace Umbraco.Cms.Infrastructure.ModelsBuilder public sealed class OutOfDateModelsStatus : INotificationHandler, INotificationHandler { - private readonly ModelsBuilderSettings _config; + private ModelsBuilderSettings _config; private readonly IHostingEnvironment _hostingEnvironment; /// /// Initializes a new instance of the class. /// - public OutOfDateModelsStatus(IOptions config, IHostingEnvironment hostingEnvironment) + public OutOfDateModelsStatus(IOptionsMonitor config, IHostingEnvironment hostingEnvironment) { - _config = config.Value; + _config = config.CurrentValue; _hostingEnvironment = hostingEnvironment; + config.OnChange(x => _config = x); } /// diff --git a/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyEditor.cs index 4b26f8eefa..d0de6e3d63 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyEditor.cs @@ -28,7 +28,7 @@ namespace Umbraco.Cms.Core.PropertyEditors INotificationHandler { private readonly MediaFileManager _mediaFileManager; - private readonly ContentSettings _contentSettings; + private readonly IOptionsMonitor _contentSettings; private readonly UploadAutoFillProperties _uploadAutoFillProperties; private readonly ILocalizedTextService _localizedTextService; private readonly IContentService _contentService; @@ -37,7 +37,7 @@ namespace Umbraco.Cms.Core.PropertyEditors public FileUploadPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, MediaFileManager mediaFileManager, - IOptions contentSettings, + IOptionsMonitor contentSettings, ILocalizedTextService localizedTextService, UploadAutoFillProperties uploadAutoFillProperties, IContentService contentService, @@ -45,7 +45,7 @@ namespace Umbraco.Cms.Core.PropertyEditors : base(dataValueEditorFactory) { _mediaFileManager = mediaFileManager ?? throw new ArgumentNullException(nameof(mediaFileManager)); - _contentSettings = contentSettings.Value; + _contentSettings = contentSettings; _localizedTextService = localizedTextService; _uploadAutoFillProperties = uploadAutoFillProperties; _contentService = contentService; @@ -62,7 +62,7 @@ namespace Umbraco.Cms.Core.PropertyEditors protected override IDataValueEditor CreateValueEditor() { var editor = DataValueEditorFactory.Create(Attribute); - editor.Validators.Add(new UploadFileTypeValidator(_localizedTextService, Options.Create(_contentSettings))); + editor.Validators.Add(new UploadFileTypeValidator(_localizedTextService, _contentSettings)); return editor; } @@ -182,7 +182,7 @@ namespace Umbraco.Cms.Core.PropertyEditors foreach (var property in properties) { - var autoFillConfig = _contentSettings.GetConfig(property.Alias); + var autoFillConfig = _contentSettings.CurrentValue.GetConfig(property.Alias); if (autoFillConfig == null) continue; foreach (var pvalue in property.Values) diff --git a/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyValueEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyValueEditor.cs index ca3132e330..4977ede5b3 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyValueEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyValueEditor.cs @@ -21,20 +21,21 @@ namespace Umbraco.Cms.Core.PropertyEditors internal class FileUploadPropertyValueEditor : DataValueEditor { private readonly MediaFileManager _mediaFileManager; - private readonly ContentSettings _contentSettings; + private ContentSettings _contentSettings; public FileUploadPropertyValueEditor( DataEditorAttribute attribute, MediaFileManager mediaFileManager, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, - IOptions contentSettings, + IOptionsMonitor contentSettings, IJsonSerializer jsonSerializer, IIOHelper ioHelper) : base(localizedTextService, shortStringHelper, jsonSerializer, ioHelper, attribute) { _mediaFileManager = mediaFileManager ?? throw new ArgumentNullException(nameof(mediaFileManager)); - _contentSettings = contentSettings.Value ?? throw new ArgumentNullException(nameof(contentSettings)); + _contentSettings = contentSettings.CurrentValue ?? throw new ArgumentNullException(nameof(contentSettings)); + contentSettings.OnChange(x => _contentSettings = x); } /// diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs index 95023cecf6..8afdb42419 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs @@ -36,7 +36,7 @@ namespace Umbraco.Cms.Core.PropertyEditors INotificationHandler { private readonly MediaFileManager _mediaFileManager; - private readonly ContentSettings _contentSettings; + private ContentSettings _contentSettings; private readonly IDataTypeService _dataTypeService; private readonly IIOHelper _ioHelper; private readonly UploadAutoFillProperties _autoFillProperties; @@ -50,7 +50,7 @@ namespace Umbraco.Cms.Core.PropertyEditors IDataValueEditorFactory dataValueEditorFactory, ILoggerFactory loggerFactory, MediaFileManager mediaFileManager, - IOptions contentSettings, + IOptionsMonitor contentSettings, IDataTypeService dataTypeService, IIOHelper ioHelper, UploadAutoFillProperties uploadAutoFillProperties, @@ -58,12 +58,14 @@ namespace Umbraco.Cms.Core.PropertyEditors : base(dataValueEditorFactory) { _mediaFileManager = mediaFileManager ?? throw new ArgumentNullException(nameof(mediaFileManager)); - _contentSettings = contentSettings.Value ?? throw new ArgumentNullException(nameof(contentSettings)); + _contentSettings = contentSettings.CurrentValue ?? throw new ArgumentNullException(nameof(contentSettings)); _dataTypeService = dataTypeService ?? throw new ArgumentNullException(nameof(dataTypeService)); _ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper)); _autoFillProperties = uploadAutoFillProperties ?? throw new ArgumentNullException(nameof(uploadAutoFillProperties)); _contentService = contentService; _logger = loggerFactory.CreateLogger(); + + contentSettings.OnChange(x => _contentSettings = x); } public bool TryGetMediaPath(string propertyEditorAlias, object value, out string mediaPath) diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyValueEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyValueEditor.cs index 10a99ccd99..4fa41bc7d3 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyValueEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyValueEditor.cs @@ -27,7 +27,7 @@ namespace Umbraco.Cms.Core.PropertyEditors { private readonly ILogger _logger; private readonly MediaFileManager _mediaFileManager; - private readonly ContentSettings _contentSettings; + private ContentSettings _contentSettings; private readonly IDataTypeService _dataTypeService; public ImageCropperPropertyValueEditor( @@ -36,7 +36,7 @@ namespace Umbraco.Cms.Core.PropertyEditors MediaFileManager mediaFileSystem, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, - IOptions contentSettings, + IOptionsMonitor contentSettings, IJsonSerializer jsonSerializer, IIOHelper ioHelper, IDataTypeService dataTypeService) @@ -44,8 +44,9 @@ namespace Umbraco.Cms.Core.PropertyEditors { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _mediaFileManager = mediaFileSystem ?? throw new ArgumentNullException(nameof(mediaFileSystem)); - _contentSettings = contentSettings.Value; + _contentSettings = contentSettings.CurrentValue; _dataTypeService = dataTypeService; + contentSettings.OnChange(x => _contentSettings = x); } /// diff --git a/src/Umbraco.Infrastructure/PropertyEditors/UploadFileTypeValidator.cs b/src/Umbraco.Infrastructure/PropertyEditors/UploadFileTypeValidator.cs index f866ed405f..9ef266357d 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/UploadFileTypeValidator.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/UploadFileTypeValidator.cs @@ -16,12 +16,14 @@ namespace Umbraco.Cms.Core.PropertyEditors internal class UploadFileTypeValidator : IValueValidator { private readonly ILocalizedTextService _localizedTextService; - private readonly ContentSettings _contentSettings; + private ContentSettings _contentSettings; - public UploadFileTypeValidator(ILocalizedTextService localizedTextService, IOptions contentSettings) + public UploadFileTypeValidator(ILocalizedTextService localizedTextService, IOptionsMonitor contentSettings) { _localizedTextService = localizedTextService; - _contentSettings = contentSettings.Value; + _contentSettings = contentSettings.CurrentValue; + + contentSettings.OnChange(x => _contentSettings = x); } public IEnumerable Validate(object value, string valueType, object dataTypeConfiguration) diff --git a/src/Umbraco.Infrastructure/Routing/ContentFinderByConfigured404.cs b/src/Umbraco.Infrastructure/Routing/ContentFinderByConfigured404.cs index aff8c40331..bb7afdb6dc 100644 --- a/src/Umbraco.Infrastructure/Routing/ContentFinderByConfigured404.cs +++ b/src/Umbraco.Infrastructure/Routing/ContentFinderByConfigured404.cs @@ -20,7 +20,7 @@ namespace Umbraco.Cms.Core.Routing { private readonly ILogger _logger; private readonly IEntityService _entityService; - private readonly ContentSettings _contentSettings; + private ContentSettings _contentSettings; private readonly IExamineManager _examineManager; private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly IVariationContextAccessor _variationContextAccessor; @@ -31,17 +31,19 @@ namespace Umbraco.Cms.Core.Routing public ContentFinderByConfigured404( ILogger logger, IEntityService entityService, - IOptions contentConfigSettings, + IOptionsMonitor contentSettings, IExamineManager examineManager, IVariationContextAccessor variationContextAccessor, IUmbracoContextAccessor umbracoContextAccessor) { _logger = logger; _entityService = entityService; - _contentSettings = contentConfigSettings.Value; + _contentSettings = contentSettings.CurrentValue; _examineManager = examineManager; _variationContextAccessor = variationContextAccessor; _umbracoContextAccessor = umbracoContextAccessor; + + contentSettings.OnChange(x => _contentSettings = x); } /// diff --git a/src/Umbraco.Infrastructure/Scoping/ScopeProvider.cs b/src/Umbraco.Infrastructure/Scoping/ScopeProvider.cs index 1da8b7bf1c..4cc354cbad 100644 --- a/src/Umbraco.Infrastructure/Scoping/ScopeProvider.cs +++ b/src/Umbraco.Infrastructure/Scoping/ScopeProvider.cs @@ -28,7 +28,7 @@ namespace Umbraco.Cms.Core.Scoping private readonly ILoggerFactory _loggerFactory; private readonly IRequestCache _requestCache; private readonly FileSystems _fileSystems; - private readonly CoreDebugSettings _coreDebugSettings; + private CoreDebugSettings _coreDebugSettings; private readonly MediaFileManager _mediaFileManager; private static readonly AsyncLocal> s_scopeStack = new AsyncLocal>(); private static readonly AsyncLocal> s_scopeContextStack = new AsyncLocal>(); @@ -36,11 +36,11 @@ namespace Umbraco.Cms.Core.Scoping private static readonly string s_contextItemKey = typeof(ScopeProvider).FullName; private readonly IEventAggregator _eventAggregator; - public ScopeProvider(IUmbracoDatabaseFactory databaseFactory, FileSystems fileSystems, IOptions coreDebugSettings, MediaFileManager mediaFileManager, ILogger logger, ILoggerFactory loggerFactory, IRequestCache requestCache, IEventAggregator eventAggregator) + public ScopeProvider(IUmbracoDatabaseFactory databaseFactory, FileSystems fileSystems, IOptionsMonitor coreDebugSettings, MediaFileManager mediaFileManager, ILogger logger, ILoggerFactory loggerFactory, IRequestCache requestCache, IEventAggregator eventAggregator) { DatabaseFactory = databaseFactory; _fileSystems = fileSystems; - _coreDebugSettings = coreDebugSettings.Value; + _coreDebugSettings = coreDebugSettings.CurrentValue; _mediaFileManager = mediaFileManager; _logger = logger; _loggerFactory = loggerFactory; @@ -48,6 +48,8 @@ namespace Umbraco.Cms.Core.Scoping _eventAggregator = eventAggregator; // take control of the FileSystems _fileSystems.IsScoped = () => AmbientScope != null && AmbientScope.ScopedFileSystems; + + coreDebugSettings.OnChange(x => _coreDebugSettings = x); } public IUmbracoDatabaseFactory DatabaseFactory { get; } diff --git a/src/Umbraco.Infrastructure/Security/BackOfficeUserStore.cs b/src/Umbraco.Infrastructure/Security/BackOfficeUserStore.cs index e656e68193..a3080570b7 100644 --- a/src/Umbraco.Infrastructure/Security/BackOfficeUserStore.cs +++ b/src/Umbraco.Infrastructure/Security/BackOfficeUserStore.cs @@ -42,7 +42,7 @@ namespace Umbraco.Cms.Core.Security IUserService userService, IEntityService entityService, IExternalLoginService externalLoginService, - IOptions globalSettings, + IOptionsSnapshot globalSettings, IUmbracoMapper mapper, BackOfficeErrorDescriber describer, AppCaches appCaches) diff --git a/src/Umbraco.Infrastructure/Security/IdentityMapDefinition.cs b/src/Umbraco.Infrastructure/Security/IdentityMapDefinition.cs index 5addc73a3f..3b51233f61 100644 --- a/src/Umbraco.Infrastructure/Security/IdentityMapDefinition.cs +++ b/src/Umbraco.Infrastructure/Security/IdentityMapDefinition.cs @@ -17,7 +17,7 @@ namespace Umbraco.Cms.Core.Security { private readonly ILocalizedTextService _textService; private readonly IEntityService _entityService; - private readonly IOptions _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly AppCaches _appCaches; public IdentityMapDefinition( @@ -28,7 +28,7 @@ namespace Umbraco.Cms.Core.Security { _textService = textService; _entityService = entityService; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _appCaches = appCaches; } @@ -37,7 +37,7 @@ namespace Umbraco.Cms.Core.Security mapper.Define( (source, context) => { - var target = new BackOfficeIdentityUser(_globalSettings.Value, source.Id, source.Groups); + var target = new BackOfficeIdentityUser(_globalSettings, source.Id, source.Groups); target.DisableChangeTracking(); return target; }, @@ -82,7 +82,7 @@ namespace Umbraco.Cms.Core.Security target.PasswordConfig = source.PasswordConfiguration; target.StartContentIds = source.StartContentIds; target.StartMediaIds = source.StartMediaIds; - target.Culture = source.GetUserCulture(_textService, _globalSettings.Value).ToString(); // project CultureInfo to string + target.Culture = source.GetUserCulture(_textService, _globalSettings).ToString(); // project CultureInfo to string target.IsApproved = source.IsApproved; target.SecurityStamp = source.SecurityStamp; target.LockoutEnd = source.IsLockedOut ? DateTime.MaxValue.ToUniversalTime() : (DateTime?)null; diff --git a/src/Umbraco.Infrastructure/Security/UmbracoUserManager.cs b/src/Umbraco.Infrastructure/Security/UmbracoUserManager.cs index bf198af1c3..733761c7ab 100644 --- a/src/Umbraco.Infrastructure/Security/UmbracoUserManager.cs +++ b/src/Umbraco.Infrastructure/Security/UmbracoUserManager.cs @@ -60,7 +60,7 @@ namespace Umbraco.Cms.Core.Security /// /// Gets the password configuration /// - public IPasswordConfiguration PasswordConfiguration { get; } + public IPasswordConfiguration PasswordConfiguration { get; private set; } /// /// Gets the IP resolver @@ -96,7 +96,7 @@ namespace Umbraco.Cms.Core.Security string password = _passwordGenerator.GeneratePassword(); return password; } - + /// /// Used to validate the password without an identity user /// Validation code is based on the default ValidatePasswordAsync code diff --git a/src/Umbraco.Infrastructure/Sync/BatchedDatabaseServerMessenger.cs b/src/Umbraco.Infrastructure/Sync/BatchedDatabaseServerMessenger.cs index 9bae34cf3e..bc58342d82 100644 --- a/src/Umbraco.Infrastructure/Sync/BatchedDatabaseServerMessenger.cs +++ b/src/Umbraco.Infrastructure/Sync/BatchedDatabaseServerMessenger.cs @@ -37,7 +37,7 @@ namespace Umbraco.Cms.Infrastructure.Sync IRequestCache requestCache, IRequestAccessor requestAccessor, LastSyncedFileManager lastSyncedFileManager, - IOptions globalSettings) + IOptionsMonitor globalSettings) : base(mainDom, cacheRefreshers, serverRoleAccessor, logger, true, syncBootStateAccessor, hostingEnvironment, cacheInstructionService, jsonSerializer, lastSyncedFileManager, globalSettings) { _requestCache = requestCache; diff --git a/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs b/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs index 10556b7fe6..b6dcc4d432 100644 --- a/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs +++ b/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs @@ -56,7 +56,7 @@ namespace Umbraco.Cms.Infrastructure.Sync ICacheInstructionService cacheInstructionService, IJsonSerializer jsonSerializer, LastSyncedFileManager lastSyncedFileManager, - IOptions globalSettings) + IOptionsMonitor globalSettings) : base(distributedEnabled) { _cancellationToken = _cancellationTokenSource.Token; @@ -69,9 +69,11 @@ namespace Umbraco.Cms.Infrastructure.Sync CacheInstructionService = cacheInstructionService; JsonSerializer = jsonSerializer; _lastSyncedFileManager = lastSyncedFileManager; - GlobalSettings = globalSettings.Value; + GlobalSettings = globalSettings.CurrentValue; _lastPruned = _lastSync = DateTime.UtcNow; _syncIdle = new ManualResetEvent(true); + + globalSettings.OnChange(x => GlobalSettings = x); using (var process = Process.GetCurrentProcess()) { // See notes on _localIdentity @@ -85,7 +87,7 @@ namespace Umbraco.Cms.Infrastructure.Sync } - public GlobalSettings GlobalSettings { get; } + public GlobalSettings GlobalSettings { get; private set; } protected ILogger Logger { get; } diff --git a/src/Umbraco.Infrastructure/Sync/SyncBootStateAccessor.cs b/src/Umbraco.Infrastructure/Sync/SyncBootStateAccessor.cs index 9a77c57965..ff6823177a 100644 --- a/src/Umbraco.Infrastructure/Sync/SyncBootStateAccessor.cs +++ b/src/Umbraco.Infrastructure/Sync/SyncBootStateAccessor.cs @@ -11,7 +11,7 @@ namespace Umbraco.Cms.Infrastructure.Sync { private readonly ILogger _logger; private readonly LastSyncedFileManager _lastSyncedFileManager; - private readonly GlobalSettings _globalSettings; + private GlobalSettings _globalSettings; private readonly ICacheInstructionService _cacheInstructionService; private SyncBootState _syncBootState; @@ -21,13 +21,15 @@ namespace Umbraco.Cms.Infrastructure.Sync public SyncBootStateAccessor( ILogger logger, LastSyncedFileManager lastSyncedFileManager, - IOptions globalSettings, + IOptionsMonitor globalSettings, ICacheInstructionService cacheInstructionService) { _logger = logger; _lastSyncedFileManager = lastSyncedFileManager; - _globalSettings = globalSettings.Value; + _globalSettings = globalSettings.CurrentValue; _cacheInstructionService = cacheInstructionService; + + globalSettings.OnChange(x => _globalSettings = x); } public SyncBootState GetSyncBootState() diff --git a/src/Umbraco.Infrastructure/WebAssets/BackOfficeWebAssets.cs b/src/Umbraco.Infrastructure/WebAssets/BackOfficeWebAssets.cs index c7e6df8cb2..34c3f65652 100644 --- a/src/Umbraco.Infrastructure/WebAssets/BackOfficeWebAssets.cs +++ b/src/Umbraco.Infrastructure/WebAssets/BackOfficeWebAssets.cs @@ -28,7 +28,7 @@ namespace Umbraco.Cms.Infrastructure.WebAssets private readonly IRuntimeMinifier _runtimeMinifier; private readonly IManifestParser _parser; - private readonly GlobalSettings _globalSettings; + private GlobalSettings _globalSettings; private readonly CustomBackOfficeAssetsCollection _customBackOfficeAssetsCollection; private readonly IHostingEnvironment _hostingEnvironment; private readonly PropertyEditorCollection _propertyEditorCollection; @@ -38,15 +38,17 @@ namespace Umbraco.Cms.Infrastructure.WebAssets IManifestParser parser, PropertyEditorCollection propertyEditorCollection, IHostingEnvironment hostingEnvironment, - IOptions globalSettings, + IOptionsMonitor globalSettings, CustomBackOfficeAssetsCollection customBackOfficeAssetsCollection) { _runtimeMinifier = runtimeMinifier; _parser = parser; _propertyEditorCollection = propertyEditorCollection; _hostingEnvironment = hostingEnvironment; - _globalSettings = globalSettings.Value; + _globalSettings = globalSettings.CurrentValue; _customBackOfficeAssetsCollection = customBackOfficeAssetsCollection; + + globalSettings.OnChange(x => _globalSettings = x); } public void CreateBundles() @@ -170,7 +172,7 @@ namespace Umbraco.Cms.Infrastructure.WebAssets switch (assetType) { - case AssetType.Javascript: + case AssetType.Javascript: _runtimeMinifier.CreateJsBundle(bundleName, BundlingOptions.OptimizedAndComposite, filePaths); break; case AssetType.Css: @@ -178,7 +180,7 @@ namespace Umbraco.Cms.Infrastructure.WebAssets break; default: throw new IndexOutOfRangeException(); - } + } } } } diff --git a/src/Umbraco.Tests.Common/TestOptionsMonitor.cs b/src/Umbraco.Tests.Common/TestOptionsMonitor.cs new file mode 100644 index 0000000000..95ccc04239 --- /dev/null +++ b/src/Umbraco.Tests.Common/TestOptionsMonitor.cs @@ -0,0 +1,16 @@ +using System; +using Microsoft.Extensions.Options; + +namespace Umbraco.Cms.Tests.Common +{ + public class TestOptionsMonitor : IOptionsMonitor where T : class + { + public TestOptionsMonitor(T currentValue) => CurrentValue = currentValue; + + public T Get(string name) => CurrentValue; + + public IDisposable OnChange(Action listener) => null; + + public T CurrentValue { get; } + } +} diff --git a/src/Umbraco.Tests.Common/TestOptionsSnapshot.cs b/src/Umbraco.Tests.Common/TestOptionsSnapshot.cs new file mode 100644 index 0000000000..9b3cdb4b2c --- /dev/null +++ b/src/Umbraco.Tests.Common/TestOptionsSnapshot.cs @@ -0,0 +1,11 @@ +using Microsoft.Extensions.Options; + +namespace Umbraco.Cms.Tests.Common +{ + public class TestOptionsSnapshot : IOptionsSnapshot where T : class + { + public TestOptionsSnapshot(T value) => Value = value; + public T Value { get; } + public T Get(string name) => Value; + } +} diff --git a/src/Umbraco.Tests.Integration/Umbraco.Core/Packaging/CreatedPackagesRepositoryTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Core/Packaging/CreatedPackagesRepositoryTests.cs index 3eca38be76..09eedb312b 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Core/Packaging/CreatedPackagesRepositoryTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Core/Packaging/CreatedPackagesRepositoryTests.cs @@ -9,14 +9,12 @@ using System.Linq; using System.Xml.Linq; using NUnit.Framework; using Umbraco.Cms.Core; -using Umbraco.Cms.Core.Configuration; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Hosting; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Packaging; using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Core.Strings; using Umbraco.Cms.Tests.Common.Builders; using Umbraco.Cms.Tests.Common.Testing; using Umbraco.Cms.Tests.Integration.Testing; diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Security/BackOfficeUserStoreTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Security/BackOfficeUserStoreTests.cs index 665bb2f079..ab5ed1dcfc 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Security/BackOfficeUserStoreTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Security/BackOfficeUserStoreTests.cs @@ -12,6 +12,7 @@ using Umbraco.Cms.Core.Models.Membership; using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Tests.Common; using Umbraco.Cms.Tests.Common.Testing; using Umbraco.Cms.Tests.Integration.Testing; @@ -33,7 +34,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Security UserService, EntityService, ExternalLoginService, - Options.Create(GlobalSettings), + new TestOptionsSnapshot(GlobalSettings), UmbracoMapper, new BackOfficeErrorDescriber(TextService), AppCaches); diff --git a/src/Umbraco.Tests.UnitTests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests.UnitTests/TestHelpers/TestHelper.cs index 8dee7db12d..01bfef40c6 100644 --- a/src/Umbraco.Tests.UnitTests/TestHelpers/TestHelper.cs +++ b/src/Umbraco.Tests.UnitTests/TestHelpers/TestHelper.cs @@ -127,7 +127,7 @@ namespace Umbraco.Cms.Tests.UnitTests.TestHelpers public static UriUtility UriUtility => s_testHelperInternal.UriUtility; - public static IEmailSender EmailSender { get; } = new EmailSender(new NullLogger(), Options.Create(new GlobalSettings()), Mock.Of()); + public static IEmailSender EmailSender { get; } = new EmailSender(new NullLogger(), new TestOptionsMonitor(new GlobalSettings()), Mock.Of()); /// /// Some test files are copied to the /bin (/bin/debug) on build, this is a utility to return their physical path based on a virtual path name diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs index 4173417582..2fb4ce2f21 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs @@ -27,6 +27,7 @@ using Umbraco.Cms.Core.Strings; using Umbraco.Cms.Infrastructure.Migrations.Install; using Umbraco.Cms.Infrastructure.Persistence; using Umbraco.Cms.Infrastructure.Persistence.Mappers; +using Umbraco.Cms.Tests.Common; using Umbraco.Cms.Tests.UnitTests.TestHelpers; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components @@ -68,7 +69,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components Mock.Of(), Options.Create(new ContentSettings())); IEventAggregator eventAggregator = Mock.Of(); - var scopeProvider = new ScopeProvider(f, fs, Options.Create(coreDebug), mediaFileManager, loggerFactory.CreateLogger(), loggerFactory, NoAppCache.Instance, eventAggregator); + var scopeProvider = new ScopeProvider(f, fs, new TestOptionsMonitor(coreDebug), mediaFileManager, loggerFactory.CreateLogger(), loggerFactory, NoAppCache.Instance, eventAggregator); mock.Setup(x => x.GetService(typeof(ILogger))).Returns(logger); mock.Setup(x => x.GetService(typeof(ILogger))).Returns(loggerFactory.CreateLogger); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Scoping/ScopeEventDispatcherTests.cs index 59eba97c59..5cb21cac3c 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Scoping/ScopeEventDispatcherTests.cs @@ -16,6 +16,7 @@ using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; using Umbraco.Cms.Infrastructure.Persistence; +using Umbraco.Cms.Tests.Common; using Umbraco.Cms.Tests.Common.Builders; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Scoping @@ -91,7 +92,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Scoping return new ScopeProvider( Mock.Of(), fileSystems, - Options.Create(new CoreDebugSettings()), + new TestOptionsMonitor(new CoreDebugSettings()), mediaFileManager, Mock.Of>(), instance, diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Scoping/ScopedNotificationPublisherTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Scoping/ScopedNotificationPublisherTests.cs index db25b946b4..5e6b3fe382 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Scoping/ScopedNotificationPublisherTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Scoping/ScopedNotificationPublisherTests.cs @@ -16,6 +16,7 @@ using Umbraco.Cms.Core.PropertyEditors; using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Strings; using Umbraco.Cms.Infrastructure.Persistence; +using Umbraco.Cms.Tests.Common; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Scoping { @@ -92,7 +93,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Scoping return new ScopeProvider( Mock.Of(), fileSystems, - Options.Create(new CoreDebugSettings()), + new TestOptionsMonitor(new CoreDebugSettings()), mediaFileManager, loggerFactory.CreateLogger(), loggerFactory, diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Templates/HtmlLocalLinkParserTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Templates/HtmlLocalLinkParserTests.cs index 670f528bbd..d171342023 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Templates/HtmlLocalLinkParserTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Templates/HtmlLocalLinkParserTests.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using Microsoft.Extensions.Options; using Moq; using NUnit.Framework; using Umbraco.Cms.Core; @@ -78,7 +79,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Templates var webRoutingSettings = new WebRoutingSettings(); var publishedUrlProvider = new UrlProvider( umbracoContextAccessor, - Microsoft.Extensions.Options.Options.Create(webRoutingSettings), + Options.Create(webRoutingSettings), new UrlProviderCollection(() => new[] { contentUrlProvider.Object }), new MediaUrlProviderCollection(() => new[] { mediaUrlProvider.Object }), Mock.Of()); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/HealthCheckNotifierTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/HealthCheckNotifierTests.cs index be581122a1..b6f94c17a8 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/HealthCheckNotifierTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/HealthCheckNotifierTests.cs @@ -20,6 +20,7 @@ using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Sync; using Umbraco.Cms.Infrastructure.HostedServices; +using Umbraco.Cms.Tests.Common; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HostedServices { @@ -149,7 +150,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HostedServices var mockProfilingLogger = new Mock(); return new HealthCheckNotifier( - Options.Create(settings), + new TestOptionsMonitor(settings), checks, notifications, mockRunTimeState.Object, diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/KeepAliveTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/KeepAliveTests.cs index 3cc23cfb45..d8efc0445c 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/KeepAliveTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/KeepAliveTests.cs @@ -18,6 +18,7 @@ using Umbraco.Cms.Core.Runtime; using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Sync; using Umbraco.Cms.Infrastructure.HostedServices; +using Umbraco.Cms.Tests.Common; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HostedServices { @@ -107,7 +108,8 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HostedServices return new KeepAlive( mockHostingEnvironment.Object, mockMainDom.Object, - Options.Create(settings), + + new TestOptionsMonitor(settings), mockLogger.Object, mockProfilingLogger.Object, mockServerRegistrar.Object, diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/LogScrubberTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/LogScrubberTests.cs index 2057167653..055224e32f 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/LogScrubberTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/LogScrubberTests.cs @@ -16,6 +16,7 @@ using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Sync; using Umbraco.Cms.Infrastructure.HostedServices; +using Umbraco.Cms.Tests.Common; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HostedServices { @@ -87,7 +88,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HostedServices mockMainDom.Object, mockServerRegistrar.Object, _mockAuditService.Object, - Options.Create(settings), + new TestOptionsMonitor(settings), mockScopeProvider.Object, mockLogger.Object, mockProfilingLogger.Object); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ServerRegistration/TouchServerTaskTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ServerRegistration/TouchServerTaskTests.cs index 29b011a5a6..793acdfa3e 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ServerRegistration/TouchServerTaskTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ServerRegistration/TouchServerTaskTests.cs @@ -12,6 +12,7 @@ using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Hosting; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Infrastructure.HostedServices.ServerRegistration; +using Umbraco.Cms.Tests.Common; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HostedServices.ServerRegistration { @@ -76,7 +77,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HostedServices.Serv _mockServerRegistrationService.Object, mockRequestAccessor.Object, mockLogger.Object, - Options.Create(settings)); + new TestOptionsMonitor(settings)); } private void VerifyServerNotTouched() => VerifyServerTouchedTimes(Times.Never()); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Scoping/ScopeUnitTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Scoping/ScopeUnitTests.cs index b699061f5a..cc4532580a 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Scoping/ScopeUnitTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Scoping/ScopeUnitTests.cs @@ -18,6 +18,7 @@ using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Strings; using Umbraco.Cms.Infrastructure.Persistence; using Umbraco.Cms.Infrastructure.Persistence.SqlSyntax; +using Umbraco.Cms.Tests.Common; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Scoping { @@ -59,7 +60,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Scoping return new ScopeProvider( databaseFactory.Object, fileSystems, - Options.Create(new CoreDebugSettings()), + new TestOptionsMonitor(new CoreDebugSettings()), mediaFileManager, loggerFactory.CreateLogger(), loggerFactory, diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Security/MemberManagerTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Security/MemberManagerTests.cs index 05afd547e1..f3edb0b8c5 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Security/MemberManagerTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Security/MemberManagerTests.cs @@ -17,6 +17,7 @@ using Umbraco.Cms.Core.PublishedCache; using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Tests.Common; using Umbraco.Cms.Tests.Common.Builders; using Umbraco.Cms.Tests.Common.Builders.Extensions; using Umbraco.Cms.Web.Common.Security; @@ -31,7 +32,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Security private Mock> _mockPasswordHasher; private Mock _mockMemberService; private Mock _mockServiceProviders; - private Mock> _mockPasswordConfiguration; + private Mock> _mockPasswordConfiguration; public MemberManager CreateSut() { @@ -43,7 +44,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Security new IdentityMapDefinition( Mock.Of(), Mock.Of(), - Options.Create(new GlobalSettings()), + new TestOptionsSnapshot(new GlobalSettings()), AppCaches.Disabled), }; @@ -64,7 +65,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Security userValidators.Add(validator.Object); _mockServiceProviders = new Mock(); - _mockPasswordConfiguration = new Mock>(); + _mockPasswordConfiguration = new Mock>(); _mockPasswordConfiguration.Setup(x => x.Value).Returns(() => new MemberPasswordConfigurationSettings() { diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Routing/RoutableDocumentFilterTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Routing/RoutableDocumentFilterTests.cs index 3613de093f..bb1c76e533 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Routing/RoutableDocumentFilterTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Routing/RoutableDocumentFilterTests.cs @@ -9,6 +9,7 @@ using NUnit.Framework; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Hosting; +using Umbraco.Cms.Tests.Common; using Umbraco.Cms.Web.Common.Routing; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Common.Routing @@ -91,7 +92,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Common.Routing var endpointDataSource = new DefaultEndpointDataSource(endpoint1, endpoint2); var routableDocFilter = new RoutableDocumentFilter( - Options.Create(globalSettings), + new TestOptionsSnapshot(globalSettings), Options.Create(routingSettings), GetHostingEnvironment(), endpointDataSource); @@ -120,7 +121,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Common.Routing var endpointDataSource = new DefaultEndpointDataSource(endpoint1); var routableDocFilter = new RoutableDocumentFilter( - Options.Create(globalSettings), + new TestOptionsSnapshot(globalSettings), Options.Create(routingSettings), GetHostingEnvironment(), endpointDataSource); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Security/MemberSignInManagerTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Security/MemberSignInManagerTests.cs index a49ba1a8ac..f553919d08 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Security/MemberSignInManagerTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Security/MemberSignInManagerTests.cs @@ -15,6 +15,7 @@ using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Net; using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Tests.Common; using Umbraco.Cms.Web.Common.Security; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Common.Security @@ -68,7 +69,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Common.Security new MembersErrorDescriber(Mock.Of()), Mock.Of(), Mock.Of>>(), - Options.Create(new MemberPasswordConfigurationSettings()), + new TestOptionsSnapshot(new MemberPasswordConfigurationSettings()), Mock.Of(), Mock.Of()); @@ -76,7 +77,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Common.Security public async Task WhenPasswordSignInAsyncIsCalled_AndEverythingIsSetup_ThenASignInResultSucceededShouldBeReturnedAsync() { //arrange - var userId = "bo8w3d32q9b98"; + var userId = "bo8w3d32q9b98"; MemberSignInManager sut = CreateSut(); var fakeUser = new MemberIdentityUser(777) { diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Controllers/RenderNoContentControllerTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Controllers/RenderNoContentControllerTests.cs index 52c976d8c1..dae3cfdb9e 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Controllers/RenderNoContentControllerTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Controllers/RenderNoContentControllerTests.cs @@ -23,7 +23,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Website.Controllers var mockUmbracoContext = new Mock(); mockUmbracoContext.Setup(x => x.Content.HasContent()).Returns(true); var mockIOHelper = new Mock(); - var controller = new RenderNoContentController(new TestUmbracoContextAccessor(mockUmbracoContext.Object), mockIOHelper.Object, Options.Create(new GlobalSettings())); + var controller = new RenderNoContentController(new TestUmbracoContextAccessor(mockUmbracoContext.Object), mockIOHelper.Object, new TestOptionsSnapshot(new GlobalSettings())); var result = controller.Index() as RedirectResult; @@ -42,7 +42,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Website.Controllers var mockIOHelper = new Mock(); mockIOHelper.Setup(x => x.ResolveUrl(It.Is(y => y == UmbracoPathSetting))).Returns(UmbracoPath); - IOptions globalSettings = Options.Create(new GlobalSettings() + var globalSettings = new TestOptionsSnapshot(new GlobalSettings() { UmbracoPath = UmbracoPathSetting, NoNodesViewPath = ViewPath, diff --git a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs index f159011d80..cc8ff205b7 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs @@ -81,11 +81,11 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IUserService userService, ILocalizedTextService textService, IUmbracoMapper umbracoMapper, - IOptions globalSettings, - IOptions securitySettings, + IOptionsSnapshot globalSettings, + IOptionsSnapshot securitySettings, ILogger logger, IIpResolver ipResolver, - IOptions passwordConfiguration, + IOptionsSnapshot passwordConfiguration, IEmailSender emailSender, ISmsSender smsSender, IHostingEnvironment hostingEnvironment, @@ -110,6 +110,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers _linkGenerator = linkGenerator; _externalAuthenticationOptions = externalAuthenticationOptions; _backOfficeTwoFactorOptions = backOfficeTwoFactorOptions; + } /// diff --git a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeAssetsController.cs b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeAssetsController.cs index 8215e8fead..bb7f86c1c9 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeAssetsController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeAssetsController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -18,7 +18,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers { private readonly IFileSystem _jsLibFileSystem; - public BackOfficeAssetsController(IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, ILoggerFactory loggerFactory, IOptions globalSettings) + public BackOfficeAssetsController(IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, ILoggerFactory loggerFactory, IOptionsSnapshot globalSettings) { var path = globalSettings.Value.UmbracoPath + Path.DirectorySeparatorChar + "lib"; _jsLibFileSystem = new PhysicalFileSystem(ioHelper, hostingEnvironment, loggerFactory.CreateLogger(), hostingEnvironment.MapPathWebRoot(path), hostingEnvironment.ToAbsolute(path)); diff --git a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs index b6df2ebf4a..c5ebe0446d 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs @@ -53,7 +53,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IBackOfficeUserManager _userManager; private readonly IRuntimeState _runtimeState; private readonly IRuntimeMinifier _runtimeMinifier; - private readonly GlobalSettings _globalSettings; + private GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly ILocalizedTextService _textService; private readonly IGridConfig _gridConfig; @@ -73,7 +73,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IBackOfficeUserManager userManager, IRuntimeState runtimeState, IRuntimeMinifier runtimeMinifier, - IOptions globalSettings, + IOptionsSnapshot globalSettings, IHostingEnvironment hostingEnvironment, ILocalizedTextService textService, IGridConfig gridConfig, diff --git a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs index a982ed1744..f9a0ff3792 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs @@ -37,57 +37,63 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly LinkGenerator _linkGenerator; private readonly IRuntimeState _runtimeState; private readonly UmbracoFeatures _features; - private readonly GlobalSettings _globalSettings; + private GlobalSettings _globalSettings; private readonly IUmbracoVersion _umbracoVersion; - private readonly ContentSettings _contentSettings; + private ContentSettings _contentSettings; private readonly TreeCollection _treeCollection; private readonly IHttpContextAccessor _httpContextAccessor; private readonly IHostingEnvironment _hostingEnvironment; - private readonly RuntimeSettings _runtimeSettings; - private readonly SecuritySettings _securitySettings; + private RuntimeSettings _runtimeSettings; + private SecuritySettings _securitySettings; private readonly IRuntimeMinifier _runtimeMinifier; private readonly IBackOfficeExternalLoginProviders _externalLogins; private readonly IImageUrlGenerator _imageUrlGenerator; private readonly PreviewRoutes _previewRoutes; private readonly IEmailSender _emailSender; - private readonly MemberPasswordConfigurationSettings _memberPasswordConfigurationSettings; + private MemberPasswordConfigurationSettings _memberPasswordConfigurationSettings; public BackOfficeServerVariables( LinkGenerator linkGenerator, IRuntimeState runtimeState, UmbracoFeatures features, - IOptions globalSettings, + IOptionsMonitor globalSettings, IUmbracoVersion umbracoVersion, - IOptions contentSettings, + IOptionsMonitor contentSettings, IHttpContextAccessor httpContextAccessor, TreeCollection treeCollection, IHostingEnvironment hostingEnvironment, - IOptions runtimeSettings, - IOptions securitySettings, + IOptionsMonitor runtimeSettings, + IOptionsMonitor securitySettings, IRuntimeMinifier runtimeMinifier, IBackOfficeExternalLoginProviders externalLogins, IImageUrlGenerator imageUrlGenerator, PreviewRoutes previewRoutes, IEmailSender emailSender, - IOptions memberPasswordConfigurationSettings) + IOptionsMonitor memberPasswordConfigurationSettings) { _linkGenerator = linkGenerator; _runtimeState = runtimeState; _features = features; - _globalSettings = globalSettings.Value; + _globalSettings = globalSettings.CurrentValue; _umbracoVersion = umbracoVersion; - _contentSettings = contentSettings.Value ?? throw new ArgumentNullException(nameof(contentSettings)); + _contentSettings = contentSettings.CurrentValue ?? throw new ArgumentNullException(nameof(contentSettings)); _httpContextAccessor = httpContextAccessor; _treeCollection = treeCollection ?? throw new ArgumentNullException(nameof(treeCollection)); _hostingEnvironment = hostingEnvironment; - _runtimeSettings = runtimeSettings.Value; - _securitySettings = securitySettings.Value; + _runtimeSettings = runtimeSettings.CurrentValue; + _securitySettings = securitySettings.CurrentValue; _runtimeMinifier = runtimeMinifier; _externalLogins = externalLogins; _imageUrlGenerator = imageUrlGenerator; _previewRoutes = previewRoutes; _emailSender = emailSender; - _memberPasswordConfigurationSettings = memberPasswordConfigurationSettings.Value; + _memberPasswordConfigurationSettings = memberPasswordConfigurationSettings.CurrentValue; + + globalSettings.OnChange(x => _globalSettings = x); + contentSettings.OnChange(x => _contentSettings = x); + runtimeSettings.OnChange(x => _runtimeSettings = x); + securitySettings.OnChange(x => _securitySettings = x); + memberPasswordConfigurationSettings.OnChange(x => _memberPasswordConfigurationSettings = x); } /// @@ -487,11 +493,13 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers // exclude anything marked with CoreTreeAttribute var coreTree = treeType.GetCustomAttribute(false); - if (coreTree != null) continue; + if (coreTree != null) + continue; // exclude anything not marked with PluginControllerAttribute var pluginController = treeType.GetCustomAttribute(false); - if (pluginController == null) continue; + if (pluginController == null) + continue; yield return new PluginTree { Alias = tree.TreeAlias, PackageFolder = pluginController.AreaName }; } diff --git a/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs b/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs index 64a47c4cc4..e5f82cc0e1 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs @@ -54,7 +54,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers ILocalizedTextService localizedTextService, IUmbracoMapper umbracoMapper, IShortStringHelper shortStringHelper, - IOptions globalSettings) + IOptionsSnapshot globalSettings) { _hostingEnvironment = hostingEnvironment; _fileSystems = fileSystems; diff --git a/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs b/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs index ba6ca36085..b3ef4b8665 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs @@ -55,7 +55,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers public CurrentUserController( MediaFileManager mediaFileManager, - IOptions contentSettings, + IOptionsSnapshot contentSettings, IHostingEnvironment hostingEnvironment, IImageUrlGenerator imageUrlGenerator, IBackOfficeSecurityAccessor backofficeSecurityAccessor, diff --git a/src/Umbraco.Web.BackOffice/Controllers/DashboardController.cs b/src/Umbraco.Web.BackOffice/Controllers/DashboardController.cs index 7b64d05633..0c6f798901 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/DashboardController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/DashboardController.cs @@ -40,7 +40,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IDashboardService _dashboardService; private readonly IUmbracoVersion _umbracoVersion; private readonly IShortStringHelper _shortStringHelper; - private readonly IOptions _dashboardSettings; + private readonly ContentDashboardSettings _dashboardSettings; /// /// Initializes a new instance of the with all its dependencies. /// @@ -51,7 +51,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IDashboardService dashboardService, IUmbracoVersion umbracoVersion, IShortStringHelper shortStringHelper, - IOptions dashboardSettings) + IOptionsSnapshot dashboardSettings) { _backOfficeSecurityAccessor = backOfficeSecurityAccessor; @@ -60,7 +60,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers _dashboardService = dashboardService; _umbracoVersion = umbracoVersion; _shortStringHelper = shortStringHelper; - _dashboardSettings = dashboardSettings; + _dashboardSettings = dashboardSettings.Value; } //we have just one instance of HttpClient shared for the entire application @@ -78,7 +78,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers var url = string.Format("{0}{1}?section={2}&allowed={3}&lang={4}&version={5}&admin={6}", baseUrl, - _dashboardSettings.Value.ContentDashboardPath, + _dashboardSettings.ContentDashboardPath, section, allowedSections, language, diff --git a/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs index 19ee05d4e9..3b6f4533ef 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs @@ -51,7 +51,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers public DataTypeController( PropertyEditorCollection propertyEditors, IDataTypeService dataTypeService, - IOptions contentSettings, + IOptionsSnapshot contentSettings, IUmbracoMapper umbracoMapper, PropertyEditorCollection propertyEditorCollection, IContentTypeService contentTypeService, diff --git a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs index 4d0e2cfe14..504b3db25f 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs @@ -45,7 +45,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers ILogger logger, ILocalizationService localizationService, IBackOfficeSecurityAccessor backofficeSecurityAccessor, - IOptions globalSettings, + IOptionsSnapshot globalSettings, ILocalizedTextService localizedTextService, IUmbracoMapper umbracoMapper ) diff --git a/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs b/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs index 310b1142c0..4e84bac0fe 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs @@ -32,7 +32,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers public LanguageController(ILocalizationService localizationService, IUmbracoMapper umbracoMapper, - IOptions globalSettings) + IOptionsSnapshot globalSettings) { _localizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService)); _umbracoMapper = umbracoMapper ?? throw new ArgumentNullException(nameof(umbracoMapper)); diff --git a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs index d54bd7a093..f3c2b7d245 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs @@ -78,7 +78,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IShortStringHelper shortStringHelper, IEventMessagesFactory eventMessages, ILocalizedTextService localizedTextService, - IOptions contentSettings, + IOptionsSnapshot contentSettings, IMediaTypeService mediaTypeService, IMediaService mediaService, IEntityService entityService, diff --git a/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs b/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs index b443a8dead..a7ba84f405 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs @@ -42,7 +42,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers public PreviewController( UmbracoFeatures features, - IOptions globalSettings, + IOptionsSnapshot globalSettings, IPublishedSnapshotService publishedSnapshotService, IBackOfficeSecurityAccessor backofficeSecurityAccessor, ILocalizationService localizationService, diff --git a/src/Umbraco.Web.BackOffice/Controllers/TinyMceController.cs b/src/Umbraco.Web.BackOffice/Controllers/TinyMceController.cs index c1d2cecc2d..cc4bc82ad6 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/TinyMceController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/TinyMceController.cs @@ -34,7 +34,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers public TinyMceController( IHostingEnvironment hostingEnvironment, IShortStringHelper shortStringHelper, - IOptions contentSettings, + IOptionsSnapshot contentSettings, IIOHelper ioHelper, IImageUrlGenerator imageUrlGenerator) { diff --git a/src/Umbraco.Web.BackOffice/Controllers/TourController.cs b/src/Umbraco.Web.BackOffice/Controllers/TourController.cs index 3b6116cc6c..63696a8dea 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/TourController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/TourController.cs @@ -29,7 +29,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers public TourController( TourFilterCollection filters, IHostingEnvironment hostingEnvironment, - IOptions tourSettings, + IOptionsSnapshot tourSettings, IBackOfficeSecurityAccessor backofficeSecurityAccessor, IContentTypeService contentTypeService) { diff --git a/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs b/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs index 145b3a658f..dad9c1d4ef 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs @@ -31,7 +31,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IUmbracoVersion umbracoVersion, ICookieManager cookieManager, IBackOfficeSecurityAccessor backofficeSecurityAccessor, - IOptions globalSettings) + IOptionsSnapshot globalSettings) { _upgradeService = upgradeService ?? throw new ArgumentNullException(nameof(upgradeService)); _umbracoVersion = umbracoVersion ?? throw new ArgumentNullException(nameof(umbracoVersion)); @@ -81,7 +81,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers { private readonly GlobalSettings _globalSettings; - public UpdateCheckResponseFilter(IOptions globalSettings) + public UpdateCheckResponseFilter(IOptionsSnapshot globalSettings) { _globalSettings = globalSettings.Value; } diff --git a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs index 7e62e514f7..677a589964 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs @@ -78,11 +78,11 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers public UsersController( MediaFileManager mediaFileManager, - IOptions contentSettings, + IOptionsSnapshot contentSettings, IHostingEnvironment hostingEnvironment, ISqlContext sqlContext, IImageUrlGenerator imageUrlGenerator, - IOptions securitySettings, + IOptionsSnapshot securitySettings, IEmailSender emailSender, IBackOfficeSecurityAccessor backofficeSecurityAccessor, AppCaches appCaches, @@ -90,7 +90,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IUserService userService, ILocalizedTextService localizedTextService, IUmbracoMapper umbracoMapper, - IOptions globalSettings, + IOptionsSnapshot globalSettings, IBackOfficeUserManager backOfficeUserManager, ILoggerFactory loggerFactory, LinkGenerator linkGenerator, diff --git a/src/Umbraco.Web.BackOffice/Filters/CheckIfUserTicketDataIsStaleAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/CheckIfUserTicketDataIsStaleAttribute.cs index 568ebab1c6..82c9e15ed5 100644 --- a/src/Umbraco.Web.BackOffice/Filters/CheckIfUserTicketDataIsStaleAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/CheckIfUserTicketDataIsStaleAttribute.cs @@ -38,7 +38,7 @@ namespace Umbraco.Cms.Web.BackOffice.Filters private readonly IUserService _userService; private readonly IEntityService _entityService; private readonly ILocalizedTextService _localizedTextService; - private readonly IOptions _globalSettings; + private GlobalSettings _globalSettings; private readonly IBackOfficeSignInManager _backOfficeSignInManager; private readonly IBackOfficeAntiforgery _backOfficeAntiforgery; private readonly IScopeProvider _scopeProvider; @@ -50,7 +50,7 @@ namespace Umbraco.Cms.Web.BackOffice.Filters IUserService userService, IEntityService entityService, ILocalizedTextService localizedTextService, - IOptions globalSettings, + IOptionsSnapshot globalSettings, IBackOfficeSignInManager backOfficeSignInManager, IBackOfficeAntiforgery backOfficeAntiforgery, IScopeProvider scopeProvider, @@ -61,7 +61,7 @@ namespace Umbraco.Cms.Web.BackOffice.Filters _userService = userService; _entityService = entityService; _localizedTextService = localizedTextService; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _backOfficeSignInManager = backOfficeSignInManager; _backOfficeAntiforgery = backOfficeAntiforgery; _scopeProvider = scopeProvider; @@ -130,7 +130,7 @@ namespace Umbraco.Cms.Web.BackOffice.Filters () => user.Username != identity.GetUsername(), () => { - CultureInfo culture = user.GetUserCulture(_localizedTextService, _globalSettings.Value); + CultureInfo culture = user.GetUserCulture(_localizedTextService, _globalSettings); return culture != null && culture.ToString() != identity.GetCultureString(); }, () => user.AllowedSections.UnsortedSequenceEqual(identity.GetAllowedApplications()) == false, diff --git a/src/Umbraco.Web.BackOffice/Filters/JsonCamelCaseFormatterAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/JsonCamelCaseFormatterAttribute.cs index c8b7683a2c..9d92dc8f8c 100644 --- a/src/Umbraco.Web.BackOffice/Filters/JsonCamelCaseFormatterAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/JsonCamelCaseFormatterAttribute.cs @@ -18,12 +18,12 @@ namespace Umbraco.Cms.Web.BackOffice.Filters private class JsonCamelCaseFormatterFilter : IResultFilter { private readonly ArrayPool _arrayPool; - private readonly IOptions _options; + private readonly MvcOptions _options; - public JsonCamelCaseFormatterFilter(ArrayPool arrayPool, IOptions options) + public JsonCamelCaseFormatterFilter(ArrayPool arrayPool, IOptionsSnapshot options) { _arrayPool = arrayPool; - _options = options; + _options = options.Value; } public void OnResultExecuted(ResultExecutedContext context) { @@ -39,11 +39,9 @@ namespace Umbraco.Cms.Web.BackOffice.Filters }; objectResult.Formatters.Clear(); - objectResult.Formatters.Add(new AngularJsonMediaTypeFormatter(serializerSettings, _arrayPool, _options.Value)); + objectResult.Formatters.Add(new AngularJsonMediaTypeFormatter(serializerSettings, _arrayPool, _options)); } } - - } } } diff --git a/src/Umbraco.Web.BackOffice/Filters/UmbracoRequireHttpsAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/UmbracoRequireHttpsAttribute.cs index b793346eba..a782d73550 100644 --- a/src/Umbraco.Web.BackOffice/Filters/UmbracoRequireHttpsAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/UmbracoRequireHttpsAttribute.cs @@ -16,7 +16,7 @@ namespace Umbraco.Cms.Web.BackOffice.Filters // just like the base class does, we'll just resolve the required services from the httpcontext. // we want to re-use their code so we don't have much choice, else we have to do some code tricks, // this is just easiest. - var optionsAccessor = filterContext.HttpContext.RequestServices.GetRequiredService>(); + var optionsAccessor = filterContext.HttpContext.RequestServices.GetRequiredService>(); if (optionsAccessor.Value.UseHttps) { // only continue if this flag is set diff --git a/src/Umbraco.Web.BackOffice/Security/BackOfficeAntiforgery.cs b/src/Umbraco.Web.BackOffice/Security/BackOfficeAntiforgery.cs index eeeced89a4..7c04ddf716 100644 --- a/src/Umbraco.Web.BackOffice/Security/BackOfficeAntiforgery.cs +++ b/src/Umbraco.Web.BackOffice/Security/BackOfficeAntiforgery.cs @@ -24,9 +24,9 @@ namespace Umbraco.Cms.Web.BackOffice.Security public class BackOfficeAntiforgery : IBackOfficeAntiforgery { private readonly IAntiforgery _internalAntiForgery; - private readonly GlobalSettings _globalSettings; + private GlobalSettings _globalSettings; - public BackOfficeAntiforgery(IOptions globalSettings) + public BackOfficeAntiforgery(IOptionsMonitor globalSettings) { // NOTE: This is the only way to create a separate IAntiForgery service :( // Everything in netcore is internal. I have logged an issue here https://github.com/dotnet/aspnetcore/issues/22217 @@ -40,7 +40,10 @@ namespace Umbraco.Cms.Web.BackOffice.Security }); ServiceProvider container = services.BuildServiceProvider(); _internalAntiForgery = container.GetRequiredService(); - _globalSettings = globalSettings.Value; + _globalSettings = globalSettings.CurrentValue; + globalSettings.OnChange(x => { + _globalSettings = x; + }); } /// diff --git a/src/Umbraco.Web.BackOffice/Security/BackOfficeSessionIdValidator.cs b/src/Umbraco.Web.BackOffice/Security/BackOfficeSessionIdValidator.cs index eadec0ee81..c085628a62 100644 --- a/src/Umbraco.Web.BackOffice/Security/BackOfficeSessionIdValidator.cs +++ b/src/Umbraco.Web.BackOffice/Security/BackOfficeSessionIdValidator.cs @@ -40,7 +40,7 @@ namespace Umbraco.Cms.Web.BackOffice.Security /// /// Initializes a new instance of the class. /// - public BackOfficeSessionIdValidator(ISystemClock systemClock, IOptions globalSettings, IBackOfficeUserManager userManager) + public BackOfficeSessionIdValidator(ISystemClock systemClock, IOptionsSnapshot globalSettings, IBackOfficeUserManager userManager) { _systemClock = systemClock; _globalSettings = globalSettings.Value; diff --git a/src/Umbraco.Web.BackOffice/Services/IconService.cs b/src/Umbraco.Web.BackOffice/Services/IconService.cs index a1d634f41b..8c5968e6b0 100644 --- a/src/Umbraco.Web.BackOffice/Services/IconService.cs +++ b/src/Umbraco.Web.BackOffice/Services/IconService.cs @@ -15,18 +15,20 @@ namespace Umbraco.Cms.Web.BackOffice.Services { public class IconService : IIconService { - private readonly IOptions _globalSettings; + private GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly IAppPolicyCache _cache; public IconService( - IOptions globalSettings, + IOptionsMonitor globalSettings, IHostingEnvironment hostingEnvironment, AppCaches appCaches) { - _globalSettings = globalSettings; + _globalSettings = globalSettings.CurrentValue; _hostingEnvironment = hostingEnvironment; _cache = appCaches.RuntimeCache; + + globalSettings.OnChange(x => _globalSettings = x); } /// @@ -114,7 +116,7 @@ namespace Umbraco.Cms.Web.BackOffice.Services } // add icons from IconsPath if not already added from plugins - var coreIconsDirectory = new DirectoryInfo(_hostingEnvironment.MapPathWebRoot($"{_globalSettings.Value.IconsPath}/")); + var coreIconsDirectory = new DirectoryInfo(_hostingEnvironment.MapPathWebRoot($"{_globalSettings.IconsPath}/")); var coreIcons = coreIconsDirectory.GetFiles("*.svg"); icons.UnionWith(coreIcons); diff --git a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreRequestAccessor.cs b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreRequestAccessor.cs index 80c1a4ddab..d140b848c8 100644 --- a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreRequestAccessor.cs +++ b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreRequestAccessor.cs @@ -15,7 +15,7 @@ namespace Umbraco.Cms.Web.Common.AspNetCore public class AspNetCoreRequestAccessor : IRequestAccessor, INotificationHandler { private readonly IHttpContextAccessor _httpContextAccessor; - private readonly WebRoutingSettings _webRoutingSettings; + private WebRoutingSettings _webRoutingSettings; private readonly ISet _applicationUrls = new HashSet(); private Uri _currentApplicationUrl; private object _initLocker = new object(); @@ -27,10 +27,11 @@ namespace Umbraco.Cms.Web.Common.AspNetCore /// public AspNetCoreRequestAccessor( IHttpContextAccessor httpContextAccessor, - IOptions webRoutingSettings) + IOptionsMonitor webRoutingSettings) { _httpContextAccessor = httpContextAccessor; - _webRoutingSettings = webRoutingSettings.Value; + _webRoutingSettings = webRoutingSettings.CurrentValue; + webRoutingSettings.OnChange(x => _webRoutingSettings = x); } @@ -40,7 +41,8 @@ namespace Umbraco.Cms.Web.Common.AspNetCore private string GetFormValue(string name) { var request = _httpContextAccessor.GetRequiredHttpContext().Request; - if (!request.HasFormContentType) return null; + if (!request.HasFormContentType) + return null; return request.Form[name]; } diff --git a/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs b/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs index cc035d116b..832b9dd92d 100644 --- a/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs @@ -109,7 +109,7 @@ namespace Umbraco.Extensions public static IApplicationBuilder UseUmbracoPluginsStaticFiles(this IApplicationBuilder app) { var hostingEnvironment = app.ApplicationServices.GetRequiredService(); - var umbracoPluginSettings = app.ApplicationServices.GetRequiredService>(); + var umbracoPluginSettings = app.ApplicationServices.GetRequiredService>(); var pluginFolder = hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.AppPlugins); diff --git a/src/Umbraco.Web.Common/Filters/AngularJsonOnlyConfigurationAttribute.cs b/src/Umbraco.Web.Common/Filters/AngularJsonOnlyConfigurationAttribute.cs index 542013577d..a12dfa3080 100644 --- a/src/Umbraco.Web.Common/Filters/AngularJsonOnlyConfigurationAttribute.cs +++ b/src/Umbraco.Web.Common/Filters/AngularJsonOnlyConfigurationAttribute.cs @@ -22,12 +22,12 @@ namespace Umbraco.Cms.Web.Common.Filters private class AngularJsonOnlyConfigurationFilter : IResultFilter { private readonly ArrayPool _arrayPool; - private readonly IOptions _options; + private MvcOptions _options; - public AngularJsonOnlyConfigurationFilter(ArrayPool arrayPool, IOptions options) + public AngularJsonOnlyConfigurationFilter(ArrayPool arrayPool, IOptionsSnapshot options) { _arrayPool = arrayPool; - _options = options; + _options = options.Value; } public void OnResultExecuted(ResultExecutedContext context) @@ -45,7 +45,7 @@ namespace Umbraco.Cms.Web.Common.Filters }; objectResult.Formatters.Clear(); - objectResult.Formatters.Add(new AngularJsonMediaTypeFormatter(serializerSettings, _arrayPool, _options.Value)); + objectResult.Formatters.Add(new AngularJsonMediaTypeFormatter(serializerSettings, _arrayPool, _options)); } } } diff --git a/src/Umbraco.Web.Common/Filters/JsonDateTimeFormatAttribute.cs b/src/Umbraco.Web.Common/Filters/JsonDateTimeFormatAttribute.cs index 8e4b04c678..98d818ba08 100644 --- a/src/Umbraco.Web.Common/Filters/JsonDateTimeFormatAttribute.cs +++ b/src/Umbraco.Web.Common/Filters/JsonDateTimeFormatAttribute.cs @@ -25,12 +25,12 @@ namespace Umbraco.Cms.Web.Common.Filters private readonly string _format = "yyyy-MM-dd HH:mm:ss"; private readonly ArrayPool _arrayPool; - private readonly IOptions _options; + private readonly MvcOptions _options; - public JsonDateTimeFormatFilter(ArrayPool arrayPool, IOptions options) + public JsonDateTimeFormatFilter(ArrayPool arrayPool, IOptionsSnapshot options) { _arrayPool = arrayPool; - _options = options; + _options = options.Value; } public void OnResultExecuted(ResultExecutedContext context) @@ -47,9 +47,8 @@ namespace Umbraco.Cms.Web.Common.Filters { DateTimeFormat = _format }); - objectResult.Formatters.Clear(); - objectResult.Formatters.Add(new AngularJsonMediaTypeFormatter(serializerSettings, _arrayPool, _options.Value)); + objectResult.Formatters.Add(new AngularJsonMediaTypeFormatter(serializerSettings, _arrayPool, _options)); } } } diff --git a/src/Umbraco.Web.Common/Filters/ModelBindingExceptionAttribute.cs b/src/Umbraco.Web.Common/Filters/ModelBindingExceptionAttribute.cs index 5b8421b9cb..1ef244dbe3 100644 --- a/src/Umbraco.Web.Common/Filters/ModelBindingExceptionAttribute.cs +++ b/src/Umbraco.Web.Common/Filters/ModelBindingExceptionAttribute.cs @@ -37,7 +37,7 @@ namespace Umbraco.Cms.Web.Common.Filters private readonly ExceptionFilterSettings _exceptionFilterSettings; private readonly IPublishedModelFactory _publishedModelFactory; - public ModelBindingExceptionFilter(IOptions exceptionFilterSettings, IPublishedModelFactory publishedModelFactory) + public ModelBindingExceptionFilter(IOptionsSnapshot exceptionFilterSettings, IPublishedModelFactory publishedModelFactory) { _exceptionFilterSettings = exceptionFilterSettings.Value; _publishedModelFactory = publishedModelFactory ?? throw new ArgumentNullException(nameof(publishedModelFactory)); diff --git a/src/Umbraco.Web.Common/Filters/OutgoingNoHyphenGuidFormatAttribute.cs b/src/Umbraco.Web.Common/Filters/OutgoingNoHyphenGuidFormatAttribute.cs index 602438008b..dd0f78fde1 100644 --- a/src/Umbraco.Web.Common/Filters/OutgoingNoHyphenGuidFormatAttribute.cs +++ b/src/Umbraco.Web.Common/Filters/OutgoingNoHyphenGuidFormatAttribute.cs @@ -18,14 +18,13 @@ namespace Umbraco.Cms.Web.Common.Filters private class OutgoingNoHyphenGuidFormatFilter : IResultFilter { - private readonly IOptions _mvcNewtonsoftJsonOptions; private readonly ArrayPool _arrayPool; - private readonly IOptions _options; + private readonly MvcOptions _options; - public OutgoingNoHyphenGuidFormatFilter(ArrayPool arrayPool, IOptions options) + public OutgoingNoHyphenGuidFormatFilter(ArrayPool arrayPool, IOptionsSnapshot options) { _arrayPool = arrayPool; - _options = options; + _options = options.Value; } public void OnResultExecuted(ResultExecutedContext context) { @@ -39,7 +38,7 @@ namespace Umbraco.Cms.Web.Common.Filters serializerSettings.Converters.Add(new GuidNoHyphenConverter()); objectResult.Formatters.Clear(); - objectResult.Formatters.Add(new AngularJsonMediaTypeFormatter(serializerSettings, _arrayPool, _options.Value)); + objectResult.Formatters.Add(new AngularJsonMediaTypeFormatter(serializerSettings, _arrayPool, _options)); } } diff --git a/src/Umbraco.Web.Common/Localization/UmbracoRequestLocalizationOptions.cs b/src/Umbraco.Web.Common/Localization/UmbracoRequestLocalizationOptions.cs index 9d8718a5f4..9cbac8fcc8 100644 --- a/src/Umbraco.Web.Common/Localization/UmbracoRequestLocalizationOptions.cs +++ b/src/Umbraco.Web.Common/Localization/UmbracoRequestLocalizationOptions.cs @@ -11,18 +11,21 @@ namespace Umbraco.Cms.Web.Common.Localization /// public class UmbracoRequestLocalizationOptions : IConfigureOptions { - private readonly IOptions _globalSettings; + private GlobalSettings _globalSettings; /// /// Initializes a new instance of the class. /// - public UmbracoRequestLocalizationOptions(IOptions globalSettings) => _globalSettings = globalSettings; + public UmbracoRequestLocalizationOptions(IOptions globalSettings) + { + _globalSettings = globalSettings.Value; + } /// public void Configure(RequestLocalizationOptions options) { // set the default culture to what is in config - options.DefaultRequestCulture = new RequestCulture(_globalSettings.Value.DefaultUILanguage); + options.DefaultRequestCulture = new RequestCulture(_globalSettings.DefaultUILanguage); // add a custom provider if (options.RequestCultureProviders == null) diff --git a/src/Umbraco.Web.Common/Macros/MacroRenderer.cs b/src/Umbraco.Web.Common/Macros/MacroRenderer.cs index fa5de8e165..3a80e555c3 100644 --- a/src/Umbraco.Web.Common/Macros/MacroRenderer.cs +++ b/src/Umbraco.Web.Common/Macros/MacroRenderer.cs @@ -28,7 +28,7 @@ namespace Umbraco.Cms.Web.Common.Macros private readonly IProfilingLogger _profilingLogger; private readonly ILogger _logger; private readonly IUmbracoContextAccessor _umbracoContextAccessor; - private readonly ContentSettings _contentSettings; + private ContentSettings _contentSettings; private readonly ILocalizedTextService _textService; private readonly AppCaches _appCaches; private readonly IMacroService _macroService; @@ -43,7 +43,7 @@ namespace Umbraco.Cms.Web.Common.Macros IProfilingLogger profilingLogger, ILogger logger, IUmbracoContextAccessor umbracoContextAccessor, - IOptions contentSettings, + IOptionsMonitor contentSettings, ILocalizedTextService textService, AppCaches appCaches, IMacroService macroService, @@ -57,7 +57,7 @@ namespace Umbraco.Cms.Web.Common.Macros _profilingLogger = profilingLogger ?? throw new ArgumentNullException(nameof(profilingLogger)); _logger = logger; _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); - _contentSettings = contentSettings.Value ?? throw new ArgumentNullException(nameof(contentSettings)); + _contentSettings = contentSettings.CurrentValue ?? throw new ArgumentNullException(nameof(contentSettings)); _textService = textService; _appCaches = appCaches ?? throw new ArgumentNullException(nameof(appCaches)); _macroService = macroService ?? throw new ArgumentNullException(nameof(macroService)); @@ -67,6 +67,8 @@ namespace Umbraco.Cms.Web.Common.Macros _requestAccessor = requestAccessor; _partialViewMacroEngine = partialViewMacroEngine; _httpContextAccessor = httpContextAccessor; + + contentSettings.OnChange(x => _contentSettings = x); } #region MacroContent cache diff --git a/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs b/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs index 539c1c844f..2b83d1e33a 100644 --- a/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs +++ b/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs @@ -53,7 +53,7 @@ namespace Umbraco.Cms.Web.Common.Middleware private readonly IRuntimeState _runtimeState; private readonly IVariationContextAccessor _variationContextAccessor; private readonly IDefaultCultureAccessor _defaultCultureAccessor; - private readonly SmidgeOptions _smidgeOptions; + private SmidgeOptions _smidgeOptions; private readonly WebProfiler _profiler; private static bool s_cacheInitialized; @@ -79,7 +79,7 @@ namespace Umbraco.Cms.Web.Common.Middleware IHostingEnvironment hostingEnvironment, UmbracoRequestPaths umbracoRequestPaths, BackOfficeWebAssets backOfficeWebAssets, - IOptions smidgeOptions, + IOptionsMonitor smidgeOptions, IRuntimeState runtimeState, IVariationContextAccessor variationContextAccessor, IDefaultCultureAccessor defaultCultureAccessor) @@ -95,8 +95,10 @@ namespace Umbraco.Cms.Web.Common.Middleware _runtimeState = runtimeState; _variationContextAccessor = variationContextAccessor; _defaultCultureAccessor = defaultCultureAccessor; - _smidgeOptions = smidgeOptions.Value; + _smidgeOptions = smidgeOptions.CurrentValue; _profiler = profiler as WebProfiler; // Ignore if not a WebProfiler + + smidgeOptions.OnChange(x => _smidgeOptions = x); } /// diff --git a/src/Umbraco.Web.Common/ModelsBuilder/InMemoryModelFactory.cs b/src/Umbraco.Web.Common/ModelsBuilder/InMemoryModelFactory.cs index 44e08f0af1..5019bbb4e3 100644 --- a/src/Umbraco.Web.Common/ModelsBuilder/InMemoryModelFactory.cs +++ b/src/Umbraco.Web.Common/ModelsBuilder/InMemoryModelFactory.cs @@ -43,7 +43,7 @@ namespace Umbraco.Cms.Web.Common.ModelsBuilder private readonly Lazy _umbracoServices; // fixme: this is because of circular refs :( private static readonly Regex s_assemblyVersionRegex = new Regex("AssemblyVersion\\(\"[0-9]+.[0-9]+.[0-9]+.[0-9]+\"\\)", RegexOptions.Compiled); private static readonly string[] s_ourFiles = { "models.hash", "models.generated.cs", "all.generated.cs", "all.dll.path", "models.err", "Compiled" }; - private readonly ModelsBuilderSettings _config; + private ModelsBuilderSettings _config; private readonly IHostingEnvironment _hostingEnvironment; private readonly IApplicationShutdownRegistry _hostingLifetime; private readonly ModelsGenerationError _errors; @@ -59,7 +59,7 @@ namespace Umbraco.Cms.Web.Common.ModelsBuilder Lazy umbracoServices, IProfilingLogger profilingLogger, ILogger logger, - IOptions config, + IOptionsMonitor config, IHostingEnvironment hostingEnvironment, IApplicationShutdownRegistry hostingLifetime, IPublishedValueFallback publishedValueFallback, @@ -68,7 +68,7 @@ namespace Umbraco.Cms.Web.Common.ModelsBuilder _umbracoServices = umbracoServices; _profilingLogger = profilingLogger; _logger = logger; - _config = config.Value; + _config = config.CurrentValue; _hostingEnvironment = hostingEnvironment; _hostingLifetime = hostingLifetime; _publishedValueFallback = publishedValueFallback; @@ -81,6 +81,7 @@ namespace Umbraco.Cms.Web.Common.ModelsBuilder return; } + config.OnChange(x => _config = x); _pureLiveDirectory = new Lazy(PureLiveDirectoryAbsolute); if (!Directory.Exists(_pureLiveDirectory.Value)) diff --git a/src/Umbraco.Web.Common/Plugins/UmbracoPluginPhysicalFileProvider.cs b/src/Umbraco.Web.Common/Plugins/UmbracoPluginPhysicalFileProvider.cs index 4259413d2d..1896d39745 100644 --- a/src/Umbraco.Web.Common/Plugins/UmbracoPluginPhysicalFileProvider.cs +++ b/src/Umbraco.Web.Common/Plugins/UmbracoPluginPhysicalFileProvider.cs @@ -2,6 +2,7 @@ // See LICENSE for more details. using System.IO; +using System.Linq; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.FileProviders.Physical; using Microsoft.Extensions.Options; @@ -18,7 +19,7 @@ namespace Umbraco.Cms.Web.Common.Plugins /// public class UmbracoPluginPhysicalFileProvider : PhysicalFileProvider, IFileProvider { - private readonly IOptions _options; + private UmbracoPluginSettings _options; /// /// Initializes a new instance of the class, at the given root directory. @@ -26,8 +27,14 @@ namespace Umbraco.Cms.Web.Common.Plugins /// The root directory. This should be an absolute path. /// The configuration options. /// Specifies which files or directories are excluded. - public UmbracoPluginPhysicalFileProvider(string root, IOptions options, ExclusionFilters filters = ExclusionFilters.Sensitive) - : base(root, filters) => _options = options; + public UmbracoPluginPhysicalFileProvider(string root, IOptionsMonitor options, ExclusionFilters filters = ExclusionFilters.Sensitive) + : base(root, filters) + { + _options = options.CurrentValue; + options.OnChange(x => { + _options = x; + } ); + } /// /// Locate a file at the given path by directly mapping path segments to physical directories. @@ -41,7 +48,7 @@ namespace Umbraco.Cms.Web.Common.Plugins { var extension = Path.GetExtension(subpath); var subPathInclAppPluginsFolder = Path.Combine(Cms.Core.Constants.SystemDirectories.AppPlugins, subpath); - if (!_options.Value.BrowsableFileExtensions.Contains(extension)) + if (!_options.BrowsableFileExtensions.Contains(extension)) { return new NotFoundFileInfo(subPathInclAppPluginsFolder); } diff --git a/src/Umbraco.Web.Common/Security/MemberManager.cs b/src/Umbraco.Web.Common/Security/MemberManager.cs index 9a0f26aff4..52bfd6a58b 100644 --- a/src/Umbraco.Web.Common/Security/MemberManager.cs +++ b/src/Umbraco.Web.Common/Security/MemberManager.cs @@ -34,7 +34,7 @@ namespace Umbraco.Cms.Web.Common.Security IdentityErrorDescriber errors, IServiceProvider services, ILogger> logger, - IOptions passwordConfiguration, + IOptionsSnapshot passwordConfiguration, IPublicAccessService publicAccessService, IHttpContextAccessor httpContextAccessor) : base(ipResolver, store, optionsAccessor, passwordHasher, userValidators, passwordValidators, errors, diff --git a/src/Umbraco.Web.Common/Templates/TemplateRenderer.cs b/src/Umbraco.Web.Common/Templates/TemplateRenderer.cs index 9dc0ef7477..92ec2fa962 100644 --- a/src/Umbraco.Web.Common/Templates/TemplateRenderer.cs +++ b/src/Umbraco.Web.Common/Templates/TemplateRenderer.cs @@ -35,7 +35,7 @@ namespace Umbraco.Cms.Web.Common.Templates private readonly IPublishedRouter _publishedRouter; private readonly IFileService _fileService; private readonly ILocalizationService _languageService; - private readonly WebRoutingSettings _webRoutingSettings; + private WebRoutingSettings _webRoutingSettings; private readonly IHttpContextAccessor _httpContextAccessor; private readonly ICompositeViewEngine _viewEngine; private readonly IModelMetadataProvider _modelMetadataProvider; @@ -46,7 +46,7 @@ namespace Umbraco.Cms.Web.Common.Templates IPublishedRouter publishedRouter, IFileService fileService, ILocalizationService textService, - IOptions webRoutingSettings, + IOptionsMonitor webRoutingSettings, IHttpContextAccessor httpContextAccessor, ICompositeViewEngine viewEngine, IModelMetadataProvider modelMetadataProvider, @@ -56,11 +56,13 @@ namespace Umbraco.Cms.Web.Common.Templates _publishedRouter = publishedRouter ?? throw new ArgumentNullException(nameof(publishedRouter)); _fileService = fileService ?? throw new ArgumentNullException(nameof(fileService)); _languageService = textService ?? throw new ArgumentNullException(nameof(textService)); - _webRoutingSettings = webRoutingSettings.Value ?? throw new ArgumentNullException(nameof(webRoutingSettings)); + _webRoutingSettings = webRoutingSettings.CurrentValue ?? throw new ArgumentNullException(nameof(webRoutingSettings)); _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor)); _viewEngine = viewEngine ?? throw new ArgumentNullException(nameof(viewEngine)); _modelMetadataProvider = modelMetadataProvider; _tempDataDictionaryFactory = tempDataDictionaryFactory; + + webRoutingSettings.OnChange(x => _webRoutingSettings = x); } public async Task RenderAsync(int pageId, int? altTemplateId, StringWriter writer) diff --git a/src/Umbraco.Web.Website/Controllers/RenderNoContentController.cs b/src/Umbraco.Web.Website/Controllers/RenderNoContentController.cs index 84c6ce08bc..04d2dd53f1 100644 --- a/src/Umbraco.Web.Website/Controllers/RenderNoContentController.cs +++ b/src/Umbraco.Web.Website/Controllers/RenderNoContentController.cs @@ -13,13 +13,13 @@ namespace Umbraco.Cms.Web.Website.Controllers { private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly IIOHelper _ioHelper; - private readonly IOptions _globalSettings; + private readonly GlobalSettings _globalSettings; - public RenderNoContentController(IUmbracoContextAccessor umbracoContextAccessor, IIOHelper ioHelper, IOptions globalSettings) + public RenderNoContentController(IUmbracoContextAccessor umbracoContextAccessor, IIOHelper ioHelper, IOptionsSnapshot globalSettings) { _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); _ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper)); - _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); + _globalSettings = globalSettings.Value ?? throw new ArgumentNullException(nameof(globalSettings)); } public ActionResult Index() @@ -34,10 +34,10 @@ namespace Umbraco.Cms.Web.Website.Controllers var model = new NoNodesViewModel { - UmbracoPath = _ioHelper.ResolveUrl(_globalSettings.Value.UmbracoPath), + UmbracoPath = _ioHelper.ResolveUrl(_globalSettings.UmbracoPath), }; - return View(_globalSettings.Value.NoNodesViewPath, model); + return View(_globalSettings.NoNodesViewPath, model); } } }