You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

250 lines
8.0 KiB
C#

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using NPin.Framework.SettingManagement.Domain.Options;
using NPin.Framework.SettingManagement.Domain.Provider;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Settings;
namespace NPin.Framework.SettingManagement.Domain;
public class SettingManager : ISettingManager, ISingletonDependency
{
private readonly Lazy<List<ISettingManagementProvider>> _lazyProviders;
protected readonly IServiceProvider ServiceProvider;
protected ISettingDefinitionManager SettingDefinitionManager { get; }
protected ISettingEncryptionService SettingEncryptionService { get; }
protected List<ISettingManagementProvider> Providers => _lazyProviders.Value;
protected SettingManagementOptions Options { get; }
public SettingManager(
IServiceProvider serviceProvider,
ISettingDefinitionManager settingDefinitionManager,
ISettingEncryptionService settingEncryptionService,
IOptions<SettingManagementOptions> options)
{
ServiceProvider = serviceProvider;
SettingDefinitionManager = settingDefinitionManager;
SettingEncryptionService = settingEncryptionService;
Options = options.Value;
_lazyProviders = new Lazy<List<ISettingManagementProvider>>(CreateSettingManagementProviders, true);
}
protected virtual List<ISettingManagementProvider> CreateSettingManagementProviders()
{
using var scope = ServiceProvider.CreateScope();
return Options.Providers
.Select(p => (scope.ServiceProvider.GetRequiredService(p) as ISettingManagementProvider)!)
.ToList();
}
public virtual Task<string?> GetOrNullAsync(string name, string providerName, string? providerKey,
bool fallback = true)
{
Check.NotNull(name, nameof(name));
Check.NotNull(providerName, nameof(providerName));
return GetOrNullInternalAsync(name, providerName, providerKey, fallback);
}
public virtual async Task<List<SettingValue>> GetAllAsync(string providerName, string? providerKey,
bool fallback = true)
{
Check.NotNull(providerName, nameof(providerName));
var settingDefinitions = await SettingDefinitionManager.GetAllAsync();
var providers = Enumerable.Reverse(Providers)
.SkipWhile(c => c.Name != providerName);
if (!fallback)
{
providers = providers.TakeWhile(c => c.Name == providerName);
}
var providerList = providers.Reverse().ToList();
if (!providerList.Any())
{
return new List<SettingValue>();
}
var settingValues = new Dictionary<string, SettingValue>();
foreach (var setting in settingDefinitions)
{
string value = null;
if (setting.IsInherited)
{
foreach (var provider in providerList)
{
var providerValue = await provider.GetOrNullAsync(
setting,
provider.Name == providerName ? providerKey : null
);
if (providerValue != null)
{
value = providerValue;
}
}
}
else
{
value = await providerList[0].GetOrNullAsync(
setting,
providerKey
);
}
if (setting.IsEncrypted)
{
value = SettingEncryptionService.Decrypt(setting, value);
}
if (value != null)
{
settingValues[setting.Name] = new SettingValue(setting.Name, value);
}
}
return settingValues.Values.ToList();
}
public async Task<Dictionary<string, SettingValue>> GetAllByPrefixAsync(string namePrefix, string providerName,
string? providerKey, bool fallback = false)
{
Check.NotNull(providerName, nameof(providerName));
var setting = await SettingDefinitionManager.GetAsync(namePrefix);
var providers = Enumerable.Reverse(Providers)
.SkipWhile(c => c.Name != providerName);
if (!fallback)
{
providers = providers.TakeWhile(c => c.Name == providerName);
}
var providerList = providers.Reverse().ToList();
if (!providerList.Any())
{
return new Dictionary<string, SettingValue>();
}
var settingValues = new Dictionary<string, SettingValue>();
foreach (var provider in providerList)
{
var list = await provider.GetByPrefixAsync(
setting.Name,
provider.Name == providerName ? providerKey : null
);
foreach (var sv in list)
{
if (setting.IsEncrypted)
{
sv.Value = SettingEncryptionService.Decrypt(setting, sv.Value);
}
if (sv.Value != null)
{
settingValues[sv.Name] = sv;
}
}
}
return settingValues;
}
public virtual async Task SetAsync(string name, string? value, string providerName, string? providerKey,
bool forceToSet = false)
{
Check.NotNull(name, nameof(name));
Check.NotNull(providerName, nameof(providerName));
var setting = await SettingDefinitionManager.GetAsync(name);
var providers = Enumerable
.Reverse(Providers)
.SkipWhile(p => p.Name != providerName)
.ToList();
if (!providers.Any())
{
return;
}
if (setting.IsEncrypted)
{
value = SettingEncryptionService.Encrypt(setting, value);
}
if (providers.Count > 1 && !forceToSet && setting.IsInherited && value != null)
{
var fallbackValue = await GetOrNullInternalAsync(name, providers[1].Name, null);
if (fallbackValue == value)
{
//Clear the value if it's same as it's fallback value
value = null;
}
}
providers = providers
.TakeWhile(p => p.Name == providerName)
.ToList(); //Getting list for case of there are more than one provider with same providerName
if (value == null)
{
foreach (var provider in providers)
{
await provider.ClearAsync(setting, providerKey);
}
}
else
{
foreach (var provider in providers)
{
await provider.SetAsync(setting, value, providerKey);
}
}
}
protected virtual async Task<string?> GetOrNullInternalAsync(string name, string? providerName, string? providerKey,
bool fallback = true)
{
var setting = await SettingDefinitionManager.GetAsync(name);
var providers = Enumerable
.Reverse(Providers);
if (providerName != null)
{
providers = providers.SkipWhile(c => c.Name != providerName);
}
if (!fallback || !setting.IsInherited)
{
providers = providers.TakeWhile(c => c.Name == providerName);
}
string value = null;
foreach (var provider in providers)
{
value = await provider.GetOrNullAsync(
setting,
provider.Name == providerName ? providerKey : null
);
if (value != null)
{
break;
}
}
if (setting.IsEncrypted)
{
value = SettingEncryptionService.Decrypt(setting, value);
}
return value;
}
}