using System; using System.Threading.Tasks; using Furion.DependencyInjection; using SqlSugar; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; namespace Waste.Domain { public class JT_Setting { public JT_Setting() { } public JT_Setting(Guid id, string name, string value, string providerName, string providerKey) { this.Id = id; this.Name = name; this.Value = value; this.ProviderName = providerName; this.ProviderKey = providerKey; } [SugarColumn(IsPrimaryKey = true)] public Guid Id { get; set; } public string Name { get; set; } public string Value { get; set; } public string ProviderName { get; set; } public string ProviderKey { get; set; } public override string ToString() { return $"{base.ToString()}, Name = {Name}, Value = {Value}, ProviderName = {ProviderName}, ProviderKey = {ProviderKey}"; } } public class SettingProvider : ITransient { private readonly IServiceProvider _serviceProvider; private readonly SettingDefinitionManager SettingDefinitionManager; private readonly SettingValueProviderManager SettingValueProviderManager; public SettingProvider(IServiceProvider serviceProvider, SettingDefinitionManager settingDefinitionManager, SettingValueProviderManager settingValueProviderManager) { _serviceProvider = serviceProvider; SettingDefinitionManager = settingDefinitionManager; SettingValueProviderManager = settingValueProviderManager; } public virtual async Task GetOrNullAsync(string name) { var setting = await SettingDefinitionManager.GetAsync(name); var providers = Enumerable .Reverse(SettingValueProviderManager.Providers); if (setting.Providers.Any()) { providers = providers.Where(p => setting.Providers.Contains(p.Name)); } //TODO: How to implement setting.IsInherited? var value = await GetOrNullValueFromProvidersAsync(providers, setting); /* if (value != null && setting.IsEncrypted) { value = SettingEncryptionService.Decrypt(setting, value); }*/ return value; } protected virtual async Task GetOrNullValueFromProvidersAsync( IEnumerable providers, SettingDefinition setting) { foreach (var provider in providers) { var value = await provider.GetOrNullAsync(setting); if (value != null) { return value; } } return null; } } public class SettingDefinitionManager : ISingleton { protected IDictionary SettingDefinitions { get; } = new Dictionary(); public SettingDefinitionManager AddSettingDefinition(SettingDefinition settingDefinition) { SettingDefinitions[settingDefinition.Name] = settingDefinition; return this; } public virtual async Task GetAsync(string name) { var setting = await GetOrNullAsync(name); if (setting == null) { throw new Exception("Undefined setting: " + name); } return setting; } public virtual Task GetOrNullAsync(string name) { return Task.FromResult(GetOrDefault(SettingDefinitions, name)); } public static TValue? GetOrDefault(IDictionary dictionary, TKey key) { return dictionary.TryGetValue(key, out var obj) ? obj : default; } } public class SettingValueProviderManager : ISingleton { public List Providers => _lazyProviders.Value; private readonly Lazy> _lazyProviders; protected IServiceProvider ServiceProvider { get; } public SettingValueProviderManager(IServiceProvider serviceProvider) { ServiceProvider = serviceProvider; _lazyProviders = new Lazy>(GetProviders, true); } protected virtual List GetProviders() { using (var scope = ServiceProvider.CreateScope()) return new List() { scope.ServiceProvider.GetRequiredService(), scope.ServiceProvider.GetRequiredService(), scope.ServiceProvider.GetRequiredService(), }; } } public class SettingManagementStore : ITransient { private readonly ISqlSugarRepository repository; public SettingManagementStore(ISqlSugarRepository repository) { this.repository = repository; } public virtual async Task GetOrNullAsync(string name, string providerName, string providerKey) { return (await FindAsync(name, providerName, providerKey))?.Value; } public virtual async Task SetAsync(string name, string value, string providerName, string providerKey) { var setting = await FindAsync(name, providerName, providerKey); if (setting == null) { setting = new JT_Setting(Guid.NewGuid(), name, value, providerName, providerKey); await repository.InsertAsync(setting); } else { setting.Value = value; await repository.UpdateAsync(setting); } } private async Task FindAsync(string name, string providerName, string providerKey) { return await repository.Where(x => x.Name == name && x.ProviderName == providerName) .WhereIF(!string.IsNullOrWhiteSpace(providerKey), x => x.ProviderKey == providerKey).FirstAsync(); } } public abstract class SettingValueProvider : ITransient { public abstract string Name { get; } protected SettingManagementStore SettingStore { get; } protected SettingValueProvider(SettingManagementStore settingStore) { SettingStore = settingStore; } public abstract Task GetOrNullAsync(SettingDefinition setting); protected virtual async Task SetAsync(string name, string value, string providerKey) { await SettingStore.SetAsync(name, value, Name, providerKey); } protected virtual async Task SetAsync(SettingDefinition setting, string value, string providerKey) { await SettingStore.SetAsync(setting.Name, value, Name, providerKey); } } public class GlobalSettingValueProvider : SettingValueProvider { public GlobalSettingValueProvider(SettingManagementStore settingStore) : base(settingStore) { } public const string ProviderName = "G"; public override string Name => ProviderName; public override Task GetOrNullAsync(SettingDefinition setting) { return SettingStore.GetOrNullAsync(setting.Name, Name, null); } public Task SetAsync(string name, string value) { return base.SetAsync(name, value, null); } } public class UserSettingValueProvider : SettingValueProvider { public const string ProviderName = "U"; public override string Name => ProviderName; protected ICurrentUser CurrentUser { get; } public UserSettingValueProvider(SettingManagementStore settingStore, ICurrentUser currentUser) : base(settingStore) { CurrentUser = currentUser; } public override async Task GetOrNullAsync(SettingDefinition setting) { if (CurrentUser.Id == null) { return null; } return await SettingStore.GetOrNullAsync(setting.Name, Name, CurrentUser.Id.ToString()); } public Task SetAsync(string name, string value) { return base.SetAsync(name, value, CurrentUser.Id.ToString()); } } public interface ICurrentUser { Guid? Id { get; } } public class DefaultValueSettingValueProvider : SettingValueProvider { public const string ProviderName = "D"; public override string Name => ProviderName; public DefaultValueSettingValueProvider(SettingManagementStore settingStore) : base(settingStore) { } public override Task GetOrNullAsync(SettingDefinition setting) { return Task.FromResult(setting.DefaultValue); } } // public Guid UserId { get; set; } public class SettingDefinition { /// /// Unique name of the setting. /// [NotNull] public string Name { get; set; } public string DisplayName { get; set; } /// /// Default value of the setting. /// public string? DefaultValue { get; set; } /// /// A list of allowed providers to get/set value of this setting. /// An empty list indicates that all providers are allowed. /// public List Providers { get; } = new List(); } }