Added support for per site options and OpenID Connect
This commit is contained in:
12
Oqtane.Server/Infrastructure/Options/ISiteOptions.cs
Normal file
12
Oqtane.Server/Infrastructure/Options/ISiteOptions.cs
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Infrastructure
|
||||
{
|
||||
public interface ISiteOptions<TOptions, TAlias>
|
||||
where TOptions : class, new()
|
||||
where TAlias : class, IAlias, new()
|
||||
{
|
||||
void Configure(TOptions options, TAlias siteOptions);
|
||||
}
|
||||
}
|
22
Oqtane.Server/Infrastructure/Options/SiteOptions.cs
Normal file
22
Oqtane.Server/Infrastructure/Options/SiteOptions.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Infrastructure
|
||||
{
|
||||
public class SiteOptions<TOptions, TAlias> : ISiteOptions<TOptions, TAlias>
|
||||
where TOptions : class, new()
|
||||
where TAlias : class, IAlias, new()
|
||||
{
|
||||
private readonly Action<TOptions, TAlias> configureOptions;
|
||||
|
||||
public SiteOptions(Action<TOptions, TAlias> configureOptions)
|
||||
{
|
||||
this.configureOptions = configureOptions;
|
||||
}
|
||||
|
||||
public void Configure(TOptions options, TAlias siteOptions)
|
||||
{
|
||||
configureOptions(options, siteOptions);
|
||||
}
|
||||
}
|
||||
}
|
70
Oqtane.Server/Infrastructure/Options/SiteOptionsCache.cs
Normal file
70
Oqtane.Server/Infrastructure/Options/SiteOptionsCache.cs
Normal file
@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Infrastructure
|
||||
{
|
||||
public class SiteOptionsCache<TOptions, TAlias> : IOptionsMonitorCache<TOptions>
|
||||
where TOptions : class
|
||||
where TAlias : class, IAlias, new()
|
||||
{
|
||||
private readonly IAliasAccessor _aliasAccessor;
|
||||
private readonly ConcurrentDictionary<string, IOptionsMonitorCache<TOptions>> map = new ConcurrentDictionary<string, IOptionsMonitorCache<TOptions>>();
|
||||
|
||||
public SiteOptionsCache(IAliasAccessor aliasAccessor)
|
||||
{
|
||||
_aliasAccessor = aliasAccessor;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
var cache = map.GetOrAdd(GetKey(), new OptionsCache<TOptions>());
|
||||
cache.Clear();
|
||||
}
|
||||
|
||||
public void Clear(Alias alias)
|
||||
{
|
||||
var cache = map.GetOrAdd(alias.SiteKey, new OptionsCache<TOptions>());
|
||||
|
||||
cache.Clear();
|
||||
}
|
||||
|
||||
public void ClearAll()
|
||||
{
|
||||
foreach (var cache in map.Values)
|
||||
{
|
||||
cache.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public TOptions GetOrAdd(string name, Func<TOptions> createOptions)
|
||||
{
|
||||
name = name ?? Options.DefaultName;
|
||||
var cache = map.GetOrAdd(GetKey(), new OptionsCache<TOptions>());
|
||||
|
||||
return cache.GetOrAdd(name, createOptions);
|
||||
}
|
||||
|
||||
public bool TryAdd(string name, TOptions options)
|
||||
{
|
||||
name = name ?? Options.DefaultName;
|
||||
var cache = map.GetOrAdd(GetKey(), new OptionsCache<TOptions>());
|
||||
|
||||
return cache.TryAdd(name, options);
|
||||
}
|
||||
|
||||
public bool TryRemove(string name)
|
||||
{
|
||||
name = name ?? Options.DefaultName;
|
||||
var cache = map.GetOrAdd(GetKey(), new OptionsCache<TOptions>());
|
||||
|
||||
return cache.TryRemove(name);
|
||||
}
|
||||
|
||||
private string GetKey()
|
||||
{
|
||||
return _aliasAccessor?.Alias?.SiteKey ?? "";
|
||||
}
|
||||
}
|
||||
}
|
77
Oqtane.Server/Infrastructure/Options/SiteOptionsFactory.cs
Normal file
77
Oqtane.Server/Infrastructure/Options/SiteOptionsFactory.cs
Normal file
@ -0,0 +1,77 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Infrastructure
|
||||
{
|
||||
public class SiteOptionsFactory<TOptions, TAlias> : IOptionsFactory<TOptions>
|
||||
where TOptions : class, new()
|
||||
where TAlias : class, IAlias, new()
|
||||
{
|
||||
private readonly IConfigureOptions<TOptions>[] _configureOptions;
|
||||
private readonly IPostConfigureOptions<TOptions>[] _postConfigureOptions;
|
||||
private readonly IValidateOptions<TOptions>[] _validations;
|
||||
private readonly ISiteOptions<TOptions, TAlias>[] _siteOptions;
|
||||
private readonly IAliasAccessor _aliasAccessor;
|
||||
|
||||
public SiteOptionsFactory(IEnumerable<IConfigureOptions<TOptions>> configureOptions, IEnumerable<IPostConfigureOptions<TOptions>> postConfigureOptions, IEnumerable<IValidateOptions<TOptions>> validations, IEnumerable<ISiteOptions<TOptions, TAlias>> siteOptions, IAliasAccessor aliasAccessor)
|
||||
{
|
||||
_configureOptions = configureOptions as IConfigureOptions<TOptions>[] ?? new List<IConfigureOptions<TOptions>>(configureOptions).ToArray();
|
||||
_postConfigureOptions = postConfigureOptions as IPostConfigureOptions<TOptions>[] ?? new List<IPostConfigureOptions<TOptions>>(postConfigureOptions).ToArray();
|
||||
_validations = validations as IValidateOptions<TOptions>[] ?? new List<IValidateOptions<TOptions>>(validations).ToArray();
|
||||
_siteOptions = siteOptions as ISiteOptions<TOptions, TAlias>[] ?? new List<ISiteOptions<TOptions, TAlias>>(siteOptions).ToArray();
|
||||
_aliasAccessor = aliasAccessor;
|
||||
}
|
||||
|
||||
public TOptions Create(string name)
|
||||
{
|
||||
// default options
|
||||
var options = new TOptions();
|
||||
foreach (var setup in _configureOptions)
|
||||
{
|
||||
if (setup is IConfigureNamedOptions<TOptions> namedSetup)
|
||||
{
|
||||
namedSetup.Configure(name, options);
|
||||
}
|
||||
else if (name == Options.DefaultName)
|
||||
{
|
||||
setup.Configure(options);
|
||||
}
|
||||
}
|
||||
|
||||
// override with site specific options
|
||||
if (_aliasAccessor?.Alias != null)
|
||||
{
|
||||
foreach (var siteOption in _siteOptions)
|
||||
{
|
||||
siteOption.Configure(options, _aliasAccessor.Alias as TAlias);
|
||||
}
|
||||
}
|
||||
|
||||
// post configuration
|
||||
foreach (var post in _postConfigureOptions)
|
||||
{
|
||||
post.PostConfigure(name, options);
|
||||
}
|
||||
|
||||
//if (_validations.Length > 0)
|
||||
//{
|
||||
// var failures = new List<string>();
|
||||
// foreach (IValidateOptions<TOptions> validate in _validations)
|
||||
// {
|
||||
// ValidateOptionsResult result = validate.Validate(name, options);
|
||||
// if (result != null && result.Failed)
|
||||
// {
|
||||
// failures.AddRange(result.Failures);
|
||||
// }
|
||||
// }
|
||||
// if (failures.Count > 0)
|
||||
// {
|
||||
// throw new OptionsValidationException(name, typeof(TOptions), failures);
|
||||
// }
|
||||
//}
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
||||
}
|
35
Oqtane.Server/Infrastructure/Options/SiteOptionsManager.cs
Normal file
35
Oqtane.Server/Infrastructure/Options/SiteOptionsManager.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Oqtane.Infrastructure
|
||||
{
|
||||
public class SiteOptionsManager<TOptions> : IOptions<TOptions>, IOptionsSnapshot<TOptions> where TOptions : class, new()
|
||||
{
|
||||
private readonly IOptionsFactory<TOptions> _factory;
|
||||
private readonly IOptionsMonitorCache<TOptions> _cache; // private cache
|
||||
|
||||
public SiteOptionsManager(IOptionsFactory<TOptions> factory, IOptionsMonitorCache<TOptions> cache)
|
||||
{
|
||||
_factory = factory;
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
public TOptions Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return Get(Options.DefaultName);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual TOptions Get(string name)
|
||||
{
|
||||
name = name ?? Options.DefaultName;
|
||||
return _cache.GetOrAdd(name, () => _factory.Create(name));
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_cache.Clear();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user