diff --git a/Yi.Abp.Net8/Yi.Abp.sln b/Yi.Abp.Net8/Yi.Abp.sln index 8a606d74..c2ba4279 100644 --- a/Yi.Abp.Net8/Yi.Abp.sln +++ b/Yi.Abp.Net8/Yi.Abp.sln @@ -121,11 +121,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.CodeGen.SqlSug EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "client", "client", "{8B27846A-043D-4F2F-8140-5CEC9D1863B5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Abp.HttpApi.Client", "client\Yi.Abp.HttpApi.Client\Yi.Abp.HttpApi.Client.csproj", "{6B554DCC-3A81-4624-9141-4E39365ADA35}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.HttpApi.Client", "client\Yi.Abp.HttpApi.Client\Yi.Abp.HttpApi.Client.csproj", "{6B554DCC-3A81-4624-9141-4E39365ADA35}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Abp.Client.Console", "client\Yi.Abp.Client.Console\Yi.Abp.Client.Console.csproj", "{2D23B44A-DFA3-4C36-8516-4F5AE442403C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Client.Console", "client\Yi.Abp.Client.Console\Yi.Abp.Client.Console.csproj", "{2D23B44A-DFA3-4C36-8516-4F5AE442403C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Abp.Client.WebApi", "client\Yi.Abp.Client.WebApi\Yi.Abp.Client.WebApi.csproj", "{00E49781-C6A0-491C-86A1-46F685C90915}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Client.WebApi", "client\Yi.Abp.Client.WebApi\Yi.Abp.Client.WebApi.csproj", "{00E49781-C6A0-491C-86A1-46F685C90915}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "setting-management", "setting-management", "{8C68059E-F3B1-4D28-A1C9-A5830F53E5D3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.SettingManagement.Domain", "module\setting-management\Yi.Framework.SettingManagement.Domain\Yi.Framework.SettingManagement.Domain.csproj", "{6FEE0EB3-EAD2-47F8-B6FC-3D0FD3CCABFF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.SettingManagement.SqlSugarCore", "module\setting-management\Yi.Framework.SettingManagement.SqlSugarCore\Yi.Framework.SettingManagement.SqlSugarCore.csproj", "{495C4643-39D4-46E7-BDC8-237589627BE4}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -321,6 +327,14 @@ Global {00E49781-C6A0-491C-86A1-46F685C90915}.Debug|Any CPU.Build.0 = Debug|Any CPU {00E49781-C6A0-491C-86A1-46F685C90915}.Release|Any CPU.ActiveCfg = Release|Any CPU {00E49781-C6A0-491C-86A1-46F685C90915}.Release|Any CPU.Build.0 = Release|Any CPU + {6FEE0EB3-EAD2-47F8-B6FC-3D0FD3CCABFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6FEE0EB3-EAD2-47F8-B6FC-3D0FD3CCABFF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6FEE0EB3-EAD2-47F8-B6FC-3D0FD3CCABFF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6FEE0EB3-EAD2-47F8-B6FC-3D0FD3CCABFF}.Release|Any CPU.Build.0 = Release|Any CPU + {495C4643-39D4-46E7-BDC8-237589627BE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {495C4643-39D4-46E7-BDC8-237589627BE4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {495C4643-39D4-46E7-BDC8-237589627BE4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {495C4643-39D4-46E7-BDC8-237589627BE4}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -378,6 +392,9 @@ Global {6B554DCC-3A81-4624-9141-4E39365ADA35} = {8B27846A-043D-4F2F-8140-5CEC9D1863B5} {2D23B44A-DFA3-4C36-8516-4F5AE442403C} = {8B27846A-043D-4F2F-8140-5CEC9D1863B5} {00E49781-C6A0-491C-86A1-46F685C90915} = {8B27846A-043D-4F2F-8140-5CEC9D1863B5} + {8C68059E-F3B1-4D28-A1C9-A5830F53E5D3} = {2317227D-7796-4E7B-BEDB-7CD1CAE7B853} + {6FEE0EB3-EAD2-47F8-B6FC-3D0FD3CCABFF} = {8C68059E-F3B1-4D28-A1C9-A5830F53E5D3} + {495C4643-39D4-46E7-BDC8-237589627BE4} = {8C68059E-F3B1-4D28-A1C9-A5830F53E5D3} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {23D6FBC9-C970-4641-BC1E-2AEA59F51C18} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/AbpSettingManagementDbProperties.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/AbpSettingManagementDbProperties.cs new file mode 100644 index 00000000..d8e2ce29 --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/AbpSettingManagementDbProperties.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Data; + +namespace Yi.Framework.SettingManagement.Domain; + +public static class AbpSettingManagementDbProperties +{ + public static string DbTablePrefix { get; set; } = AbpCommonDbProperties.DbTablePrefix; + + public static string DbSchema { get; set; } = AbpCommonDbProperties.DbSchema; + + public const string ConnectionStringName = "AbpSettingManagement"; +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/ConfigurationSettingManagementProvider.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/ConfigurationSettingManagementProvider.cs new file mode 100644 index 00000000..57a9cfbc --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/ConfigurationSettingManagementProvider.cs @@ -0,0 +1,34 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Volo.Abp; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Settings; + +namespace Yi.Framework.SettingManagement.Domain; + +public class ConfigurationSettingManagementProvider : ISettingManagementProvider, ITransientDependency +{ + public string Name => ConfigurationSettingValueProvider.ProviderName; + + protected IConfiguration Configuration { get; } + + public ConfigurationSettingManagementProvider(IConfiguration configuration) + { + Configuration = configuration; + } + + public virtual Task GetOrNullAsync(SettingDefinition setting, string providerKey) + { + return Task.FromResult(Configuration[ConfigurationSettingValueProvider.ConfigurationNamePrefix + setting.Name]); + } + + public virtual Task SetAsync(SettingDefinition setting, string value, string providerKey) + { + throw new AbpException($"Can not set a setting value to the application configuration."); + } + + public virtual Task ClearAsync(SettingDefinition setting, string providerKey) + { + throw new AbpException($"Can not set a setting value to the application configuration."); + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/ConfigurationValueSettingManagerExtensions.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/ConfigurationValueSettingManagerExtensions.cs new file mode 100644 index 00000000..80a02891 --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/ConfigurationValueSettingManagerExtensions.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Volo.Abp.Settings; + +namespace Yi.Framework.SettingManagement.Domain; + +public static class ConfigurationValueSettingManagerExtensions +{ + public static Task GetOrNullConfigurationAsync(this ISettingManager settingManager, [NotNull] string name, bool fallback = true) + { + return settingManager.GetOrNullAsync(name, ConfigurationSettingValueProvider.ProviderName, null, fallback); + } + + public static Task> GetAllConfigurationAsync(this ISettingManager settingManager, bool fallback = true) + { + return settingManager.GetAllAsync(ConfigurationSettingValueProvider.ProviderName, null, fallback); + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/DefaultValueSettingManagementProvider.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/DefaultValueSettingManagementProvider.cs new file mode 100644 index 00000000..1b69c977 --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/DefaultValueSettingManagementProvider.cs @@ -0,0 +1,26 @@ +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Settings; + +namespace Yi.Framework.SettingManagement.Domain; + +public class DefaultValueSettingManagementProvider : ISettingManagementProvider, ISingletonDependency +{ + public string Name => DefaultValueSettingValueProvider.ProviderName; + + public virtual Task GetOrNullAsync(SettingDefinition setting, string providerKey) + { + return Task.FromResult(setting.DefaultValue); + } + + public virtual Task SetAsync(SettingDefinition setting, string value, string providerKey) + { + throw new AbpException($"Can not set default value of a setting. It is only possible while defining the setting in a {typeof(ISettingDefinitionProvider)} implementation."); + } + + public virtual Task ClearAsync(SettingDefinition setting, string providerKey) + { + throw new AbpException($"Can not clear default value of a setting. It is only possible while defining the setting in a {typeof(ISettingDefinitionProvider)} implementation."); + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/DefaultValueSettingManagerExtensions.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/DefaultValueSettingManagerExtensions.cs new file mode 100644 index 00000000..de56e5dd --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/DefaultValueSettingManagerExtensions.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Volo.Abp.Settings; + +namespace Yi.Framework.SettingManagement.Domain; + +public static class DefaultValueSettingManagerExtensions +{ + public static Task GetOrNullDefaultAsync(this ISettingManager settingManager, [NotNull] string name, bool fallback = true) + { + return settingManager.GetOrNullAsync(name, DefaultValueSettingValueProvider.ProviderName, null, fallback); + } + + public static Task> GetAllDefaultAsync(this ISettingManager settingManager, bool fallback = true) + { + return settingManager.GetAllAsync(DefaultValueSettingValueProvider.ProviderName, null, fallback); + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/GlobalSettingManagementProvider.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/GlobalSettingManagementProvider.cs new file mode 100644 index 00000000..4d12a5d9 --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/GlobalSettingManagementProvider.cs @@ -0,0 +1,20 @@ +using Volo.Abp.DependencyInjection; +using Volo.Abp.Settings; + +namespace Yi.Framework.SettingManagement.Domain; + +public class GlobalSettingManagementProvider : SettingManagementProvider, ITransientDependency +{ + public override string Name => GlobalSettingValueProvider.ProviderName; + + public GlobalSettingManagementProvider(ISettingManagementStore settingManagementStore) + : base(settingManagementStore) + { + + } + + protected override string NormalizeProviderKey(string providerKey) + { + return null; + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/GlobalSettingManagerExtensions.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/GlobalSettingManagerExtensions.cs new file mode 100644 index 00000000..48ade803 --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/GlobalSettingManagerExtensions.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Volo.Abp.Settings; + +namespace Yi.Framework.SettingManagement.Domain; + +public static class GlobalSettingManagerExtensions +{ + public static Task GetOrNullGlobalAsync(this ISettingManager settingManager, [NotNull] string name, bool fallback = true) + { + return settingManager.GetOrNullAsync(name, GlobalSettingValueProvider.ProviderName, null, fallback); + } + + public static Task> GetAllGlobalAsync(this ISettingManager settingManager, bool fallback = true) + { + return settingManager.GetAllAsync(GlobalSettingValueProvider.ProviderName, null, fallback); + } + + public static Task SetGlobalAsync(this ISettingManager settingManager, [NotNull] string name, [CanBeNull] string value) + { + return settingManager.SetAsync(name, value, GlobalSettingValueProvider.ProviderName, null); + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/ISettingManagementProvider.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/ISettingManagementProvider.cs new file mode 100644 index 00000000..8b22b00c --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/ISettingManagementProvider.cs @@ -0,0 +1,16 @@ +using System.Threading.Tasks; +using JetBrains.Annotations; +using Volo.Abp.Settings; + +namespace Yi.Framework.SettingManagement.Domain; + +public interface ISettingManagementProvider +{ + string Name { get; } + + Task GetOrNullAsync([NotNull] SettingDefinition setting, [CanBeNull] string providerKey); + + Task SetAsync([NotNull] SettingDefinition setting, [NotNull] string value, [CanBeNull] string providerKey); + + Task ClearAsync([NotNull] SettingDefinition setting, [CanBeNull] string providerKey); +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/ISettingManagementStore.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/ISettingManagementStore.cs new file mode 100644 index 00000000..8a9e019a --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/ISettingManagementStore.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Settings; + +namespace Yi.Framework.SettingManagement.Domain; + +public interface ISettingManagementStore +{ + Task GetOrNullAsync(string name, string providerName, string providerKey); + + Task> GetListAsync(string providerName, string providerKey); + + Task> GetListAsync(string[] names, string providerName, string providerKey); + + Task SetAsync(string name, string value, string providerName, string providerKey); + + Task DeleteAsync(string name, string providerName, string providerKey); +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/ISettingManager.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/ISettingManager.cs new file mode 100644 index 00000000..78536044 --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/ISettingManager.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Volo.Abp.Settings; + +namespace Yi.Framework.SettingManagement.Domain; + +public interface ISettingManager +{ + Task GetOrNullAsync([NotNull] string name, [NotNull] string providerName, [CanBeNull] string providerKey, bool fallback = true); + + Task> GetAllAsync([NotNull] string providerName, [CanBeNull] string providerKey, bool fallback = true); + + Task SetAsync([NotNull] string name, [CanBeNull] string value, [NotNull] string providerName, [CanBeNull] string providerKey, bool forceToSet = false); +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/ISettingRepository.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/ISettingRepository.cs new file mode 100644 index 00000000..b45823db --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/ISettingRepository.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; + +namespace Yi.Framework.SettingManagement.Domain; + +public interface ISettingRepository : IBasicRepository +{ + Task FindAsync( + string name, + string providerName, + string providerKey, + CancellationToken cancellationToken = default); + + Task> GetListAsync( + string providerName, + string providerKey, + CancellationToken cancellationToken = default); + + Task> GetListAsync( + string[] names, + string providerName, + string providerKey, + CancellationToken cancellationToken = default); +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingCacheItem.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingCacheItem.cs new file mode 100644 index 00000000..b126c122 --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingCacheItem.cs @@ -0,0 +1,36 @@ +using System; +using System.Linq; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Text.Formatting; + +namespace Yi.Framework.SettingManagement.Domain; + +[Serializable] +[IgnoreMultiTenancy] +public class SettingCacheItem +{ + private const string CacheKeyFormat = "pn:{0},pk:{1},n:{2}"; + + public string Value { get; set; } + + public SettingCacheItem() + { + + } + + public SettingCacheItem(string value) + { + Value = value; + } + + public static string CalculateCacheKey(string name, string providerName, string providerKey) + { + return string.Format(CacheKeyFormat, providerName, providerKey, name); + } + + public static string GetSettingNameFormCacheKeyOrNull(string cacheKey) + { + var result = FormattedStringValueExtracter.Extract(cacheKey, CacheKeyFormat, true); + return result.IsMatch ? result.Matches.Last().Value : null; + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingCacheItemInvalidator.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingCacheItemInvalidator.cs new file mode 100644 index 00000000..c8c5278a --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingCacheItemInvalidator.cs @@ -0,0 +1,33 @@ +using System.Threading.Tasks; +using Volo.Abp.Caching; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Entities.Events; +using Volo.Abp.EventBus; + +namespace Yi.Framework.SettingManagement.Domain; + +public class SettingCacheItemInvalidator : ILocalEventHandler>, ITransientDependency +{ + protected IDistributedCache Cache { get; } + + public SettingCacheItemInvalidator(IDistributedCache cache) + { + Cache = cache; + } + + public virtual async Task HandleEventAsync(EntityChangedEventData eventData) + { + var cacheKey = CalculateCacheKey( + eventData.Entity.Name, + eventData.Entity.ProviderName, + eventData.Entity.ProviderKey + ); + + await Cache.RemoveAsync(cacheKey, considerUow: true); + } + + protected virtual string CalculateCacheKey(string name, string providerName, string providerKey) + { + return SettingCacheItem.CalculateCacheKey(name, providerName, providerKey); + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingEntity.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingEntity.cs new file mode 100644 index 00000000..619dc64c --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingEntity.cs @@ -0,0 +1,47 @@ +using JetBrains.Annotations; +using Volo.Abp; +using Volo.Abp.Domain.Entities; + +namespace Yi.Framework.SettingManagement.Domain; + +public class SettingEntity : Entity, IAggregateRoot +{ + [NotNull] + public virtual string Name { get; protected set; } + + [NotNull] + public virtual string Value { get; internal set; } + + [CanBeNull] + public virtual string ProviderName { get; protected set; } + + [CanBeNull] + public virtual string ProviderKey { get; protected set; } + + public SettingEntity() + { + + } + + public SettingEntity( + Guid id, + [NotNull] string name, + [NotNull] string value, + [CanBeNull] string providerName = null, + [CanBeNull] string providerKey = null) + { + Check.NotNull(name, nameof(name)); + Check.NotNull(value, nameof(value)); + + Id = id; + Name = name; + Value = value; + ProviderName = providerName; + ProviderKey = providerKey; + } + + public override string ToString() + { + return $"{base.ToString()}, Name = {Name}, Value = {Value}, ProviderName = {ProviderName}, ProviderKey = {ProviderKey}"; + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingManagementOptions.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingManagementOptions.cs new file mode 100644 index 00000000..d02446cc --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingManagementOptions.cs @@ -0,0 +1,13 @@ +using Volo.Abp.Collections; + +namespace Yi.Framework.SettingManagement.Domain; + +public class SettingManagementOptions +{ + public ITypeList Providers { get; } + + public SettingManagementOptions() + { + Providers = new TypeList(); + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingManagementProvider.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingManagementProvider.cs new file mode 100644 index 00000000..1bc6b3c4 --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingManagementProvider.cs @@ -0,0 +1,37 @@ +using System.Threading.Tasks; +using Volo.Abp.Settings; + +namespace Yi.Framework.SettingManagement.Domain; + +public abstract class SettingManagementProvider : ISettingManagementProvider +{ + public abstract string Name { get; } + + //TODO: Rename to Store + protected ISettingManagementStore SettingManagementStore { get; } + + protected SettingManagementProvider(ISettingManagementStore settingManagementStore) + { + SettingManagementStore = settingManagementStore; + } + + public virtual async Task GetOrNullAsync(SettingDefinition setting, string providerKey) + { + return await SettingManagementStore.GetOrNullAsync(setting.Name, Name, NormalizeProviderKey(providerKey)); + } + + public virtual async Task SetAsync(SettingDefinition setting, string value, string providerKey) + { + await SettingManagementStore.SetAsync(setting.Name, value, Name, NormalizeProviderKey(providerKey)); + } + + public virtual async Task ClearAsync(SettingDefinition setting, string providerKey) + { + await SettingManagementStore.DeleteAsync(setting.Name, Name, NormalizeProviderKey(providerKey)); + } + + protected virtual string NormalizeProviderKey(string providerKey) + { + return providerKey; + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingManagementStore.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingManagementStore.cs new file mode 100644 index 00000000..86a52d45 --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingManagementStore.cs @@ -0,0 +1,214 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Caching; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; +using Volo.Abp.Settings; +using Volo.Abp.Uow; + +namespace Yi.Framework.SettingManagement.Domain; + +public class SettingManagementStore : ISettingManagementStore, ITransientDependency +{ + protected IDistributedCache Cache { get; } + protected ISettingDefinitionManager SettingDefinitionManager { get; } + protected ISettingRepository SettingRepository { get; } + protected IGuidGenerator GuidGenerator { get; } + + public SettingManagementStore( + ISettingRepository settingRepository, + IGuidGenerator guidGenerator, + IDistributedCache cache, + ISettingDefinitionManager settingDefinitionManager) + { + SettingRepository = settingRepository; + GuidGenerator = guidGenerator; + Cache = cache; + SettingDefinitionManager = settingDefinitionManager; + } + + [UnitOfWork] + public virtual async Task GetOrNullAsync(string name, string providerName, string providerKey) + { + return (await GetCacheItemAsync(name, providerName, providerKey)).Value; + } + + [UnitOfWork] + public virtual async Task SetAsync(string name, string value, string providerName, string providerKey) + { + var setting = await SettingRepository.FindAsync(name, providerName, providerKey); + if (setting == null) + { + setting = new SettingEntity(GuidGenerator.Create(), name, value, providerName, providerKey); + await SettingRepository.InsertAsync(setting); + } + else + { + setting.Value = value; + await SettingRepository.UpdateAsync(setting); + } + + await Cache.SetAsync(CalculateCacheKey(name, providerName, providerKey), new SettingCacheItem(setting?.Value), considerUow: true); + } + + public virtual async Task> GetListAsync(string providerName, string providerKey) + { + var settings = await SettingRepository.GetListAsync(providerName, providerKey); + return settings.Select(s => new SettingValue(s.Name, s.Value)).ToList(); + } + + [UnitOfWork] + public virtual async Task DeleteAsync(string name, string providerName, string providerKey) + { + var setting = await SettingRepository.FindAsync(name, providerName, providerKey); + if (setting != null) + { + await SettingRepository.DeleteAsync(setting); + await Cache.RemoveAsync(CalculateCacheKey(name, providerName, providerKey), considerUow: true); + } + } + + protected virtual async Task GetCacheItemAsync(string name, string providerName, string providerKey) + { + var cacheKey = CalculateCacheKey(name, providerName, providerKey); + var cacheItem = await Cache.GetAsync(cacheKey, considerUow: true); + + if (cacheItem != null) + { + return cacheItem; + } + + cacheItem = new SettingCacheItem(null); + + await SetCacheItemsAsync(providerName, providerKey, name, cacheItem); + + return cacheItem; + } + + private async Task SetCacheItemsAsync( + string providerName, + string providerKey, + string currentName, + SettingCacheItem currentCacheItem) + { + var settingDefinitions =await SettingDefinitionManager.GetAllAsync(); + var settingsDictionary = (await SettingRepository.GetListAsync(providerName, providerKey)) + .ToDictionary(s => s.Name, s => s.Value); + + var cacheItems = new List>(); + + foreach (var settingDefinition in settingDefinitions) + { + var settingValue = settingsDictionary.GetOrDefault(settingDefinition.Name); + + cacheItems.Add( + new KeyValuePair( + CalculateCacheKey(settingDefinition.Name, providerName, providerKey), + new SettingCacheItem(settingValue) + ) + ); + + if (settingDefinition.Name == currentName) + { + currentCacheItem.Value = settingValue; + } + } + + await Cache.SetManyAsync(cacheItems, considerUow: true); + } + + [UnitOfWork] + public async Task> GetListAsync(string[] names, string providerName, string providerKey) + { + Check.NotNullOrEmpty(names, nameof(names)); + + var result = new List(); + + if (names.Length == 1) + { + var name = names.First(); + result.Add(new SettingValue(name, (await GetCacheItemAsync(name, providerName, providerKey)).Value)); + return result; + } + + var cacheItems = await GetCacheItemsAsync(names, providerName, providerKey); + foreach (var item in cacheItems) + { + result.Add(new SettingValue(GetSettingNameFormCacheKeyOrNull(item.Key), item.Value?.Value)); + } + + return result; + } + + protected virtual async Task>> GetCacheItemsAsync(string[] names, string providerName, string providerKey) + { + var cacheKeys = names.Select(x => CalculateCacheKey(x, providerName, providerKey)).ToList(); + + var cacheItems = (await Cache.GetManyAsync(cacheKeys, considerUow: true)).ToList(); + + if (cacheItems.All(x => x.Value != null)) + { + return cacheItems; + } + + var notCacheKeys = cacheItems.Where(x => x.Value == null).Select(x => x.Key).ToList(); + + var newCacheItems = await SetCacheItemsAsync(providerName, providerKey, notCacheKeys); + + var result = new List>(); + foreach (var key in cacheKeys) + { + var item = newCacheItems.FirstOrDefault(x => x.Key == key); + if (item.Value == null) + { + item = cacheItems.FirstOrDefault(x => x.Key == key); + } + + result.Add(new KeyValuePair(key, item.Value)); + } + + return result; + } + + private async Task>> SetCacheItemsAsync( + string providerName, + string providerKey, + List notCacheKeys) + { + var settingDefinitions =(await SettingDefinitionManager.GetAllAsync()).Where(x => notCacheKeys.Any(k => GetSettingNameFormCacheKeyOrNull(k) == x.Name)); + + var settingsDictionary = (await SettingRepository.GetListAsync(notCacheKeys.Select(GetSettingNameFormCacheKeyOrNull).ToArray(), providerName, providerKey)) + .ToDictionary(s => s.Name, s => s.Value); + + var cacheItems = new List>(); + + foreach (var settingDefinition in settingDefinitions) + { + var settingValue = settingsDictionary.GetOrDefault(settingDefinition.Name); + cacheItems.Add( + new KeyValuePair( + CalculateCacheKey(settingDefinition.Name, providerName, providerKey), + new SettingCacheItem(settingValue) + ) + ); + } + + await Cache.SetManyAsync(cacheItems, considerUow: true); + + return cacheItems; + } + + + protected virtual string CalculateCacheKey(string name, string providerName, string providerKey) + { + return SettingCacheItem.CalculateCacheKey(name, providerName, providerKey); + } + + protected virtual string GetSettingNameFormCacheKeyOrNull(string key) + { + //TODO: throw ex when name is null? + return SettingCacheItem.GetSettingNameFormCacheKeyOrNull(key); + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingManager.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingManager.cs new file mode 100644 index 00000000..3a01251b --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingManager.cs @@ -0,0 +1,201 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Settings; + +namespace Yi.Framework.SettingManagement.Domain; + +public class SettingManager : ISettingManager, ISingletonDependency +{ + protected ISettingDefinitionManager SettingDefinitionManager { get; } + protected ISettingEncryptionService SettingEncryptionService { get; } + protected List Providers => _lazyProviders.Value; + protected SettingManagementOptions Options { get; } + private readonly Lazy> _lazyProviders; + + public SettingManager( + IOptions options, + IServiceProvider serviceProvider, + ISettingDefinitionManager settingDefinitionManager, + ISettingEncryptionService settingEncryptionService) + { + SettingDefinitionManager = settingDefinitionManager; + SettingEncryptionService = settingEncryptionService; + Options = options.Value; + + //TODO: Instead, use IServiceScopeFactory and create a scope..? + + _lazyProviders = new Lazy>( + () => Options + .Providers + .Select(c => serviceProvider.GetRequiredService(c) as ISettingManagementProvider) + .ToList(), + true + ); + } + + public virtual Task 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> 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(); + } + + var settingValues = new Dictionary(); + + 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 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 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; + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingStore.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingStore.cs new file mode 100644 index 00000000..8de5ca62 --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/SettingStore.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Settings; + +namespace Yi.Framework.SettingManagement.Domain; + +public class SettingStore : ISettingStore, ITransientDependency +{ + protected ISettingManagementStore ManagementStore { get; } + + public SettingStore(ISettingManagementStore managementStore) + { + ManagementStore = managementStore; + } + + public virtual Task GetOrNullAsync(string name, string providerName, string providerKey) + { + return ManagementStore.GetOrNullAsync(name, providerName, providerKey); + } + + public virtual Task> GetAllAsync(string[] names, string providerName, string providerKey) + { + return ManagementStore.GetListAsync(names, providerName, providerKey); + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/TenantSettingManagementProvider.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/TenantSettingManagementProvider.cs new file mode 100644 index 00000000..bd4d88ae --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/TenantSettingManagementProvider.cs @@ -0,0 +1,30 @@ +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Settings; + +namespace Yi.Framework.SettingManagement.Domain; + +public class TenantSettingManagementProvider : SettingManagementProvider, ITransientDependency +{ + public override string Name => TenantSettingValueProvider.ProviderName; + + protected ICurrentTenant CurrentTenant { get; } + + public TenantSettingManagementProvider( + ISettingManagementStore settingManagementStore, + ICurrentTenant currentTenant) + : base(settingManagementStore) + { + CurrentTenant = currentTenant; + } + + protected override string NormalizeProviderKey(string providerKey) + { + if (providerKey != null) + { + return providerKey; + } + + return CurrentTenant.Id?.ToString(); + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/TenantSettingManagerExtensions.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/TenantSettingManagerExtensions.cs new file mode 100644 index 00000000..2398df8d --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/TenantSettingManagerExtensions.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Volo.Abp.Settings; + +namespace Yi.Framework.SettingManagement.Domain; + +public static class TenantSettingManagerExtensions +{ + public static Task GetOrNullForTenantAsync(this ISettingManager settingManager, [NotNull] string name, Guid tenantId, bool fallback = true) + { + return settingManager.GetOrNullAsync(name, TenantSettingValueProvider.ProviderName, tenantId.ToString(), fallback); + } + + public static Task GetOrNullForCurrentTenantAsync(this ISettingManager settingManager, [NotNull] string name, bool fallback = true) + { + return settingManager.GetOrNullAsync(name, TenantSettingValueProvider.ProviderName, null, fallback); + } + + public static Task> GetAllForTenantAsync(this ISettingManager settingManager, Guid tenantId, bool fallback = true) + { + return settingManager.GetAllAsync(TenantSettingValueProvider.ProviderName, tenantId.ToString(), fallback); + } + + public static Task> GetAllForCurrentTenantAsync(this ISettingManager settingManager, bool fallback = true) + { + return settingManager.GetAllAsync(TenantSettingValueProvider.ProviderName, null, fallback); + } + + public static Task SetForTenantAsync(this ISettingManager settingManager, Guid tenantId, [NotNull] string name, [CanBeNull] string value, bool forceToSet = false) + { + return settingManager.SetAsync(name, value, TenantSettingValueProvider.ProviderName, tenantId.ToString(), forceToSet); + } + + public static Task SetForCurrentTenantAsync(this ISettingManager settingManager, [NotNull] string name, [CanBeNull] string value, bool forceToSet = false) + { + return settingManager.SetAsync(name, value, TenantSettingValueProvider.ProviderName, null, forceToSet); + } + + public static Task SetForTenantOrGlobalAsync(this ISettingManager settingManager, Guid? tenantId, [NotNull] string name, [CanBeNull] string value, bool forceToSet = false) + { + if (tenantId.HasValue) + { + return settingManager.SetForTenantAsync(tenantId.Value, name, value, forceToSet); + } + + return settingManager.SetGlobalAsync(name, value); + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/UserSettingManagementProvider.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/UserSettingManagementProvider.cs new file mode 100644 index 00000000..ea2cecae --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/UserSettingManagementProvider.cs @@ -0,0 +1,30 @@ +using Volo.Abp.DependencyInjection; +using Volo.Abp.Settings; +using Volo.Abp.Users; + +namespace Yi.Framework.SettingManagement.Domain; + +public class UserSettingManagementProvider : SettingManagementProvider, ITransientDependency +{ + public override string Name => UserSettingValueProvider.ProviderName; + + protected ICurrentUser CurrentUser { get; } + + public UserSettingManagementProvider( + ISettingManagementStore settingManagementStore, + ICurrentUser currentUser) + : base(settingManagementStore) + { + CurrentUser = currentUser; + } + + protected override string NormalizeProviderKey(string providerKey) + { + if (providerKey != null) + { + return providerKey; + } + + return CurrentUser.Id?.ToString(); + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/UserSettingManagerExtensions.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/UserSettingManagerExtensions.cs new file mode 100644 index 00000000..8c7dd58f --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/UserSettingManagerExtensions.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Volo.Abp.Settings; +using Volo.Abp.Users; + +namespace Yi.Framework.SettingManagement.Domain; + +//TODO: Consider to move to another package? + +public static class UserSettingManagerExtensions +{ + public static Task GetOrNullForUserAsync(this ISettingManager settingManager, [NotNull] string name, Guid userId, bool fallback = true) + { + return settingManager.GetOrNullAsync(name, UserSettingValueProvider.ProviderName, userId.ToString(), fallback); + } + + public static Task GetOrNullForCurrentUserAsync(this ISettingManager settingManager, [NotNull] string name, bool fallback = true) + { + return settingManager.GetOrNullAsync(name, UserSettingValueProvider.ProviderName, null, fallback); + } + + public static Task> GetAllForUserAsync(this ISettingManager settingManager, Guid userId, bool fallback = true) + { + return settingManager.GetAllAsync(UserSettingValueProvider.ProviderName, userId.ToString(), fallback); + } + + public static Task> GetAllForCurrentUserAsync(this ISettingManager settingManager, bool fallback = true) + { + return settingManager.GetAllAsync(UserSettingValueProvider.ProviderName, null, fallback); + } + + public static Task SetForUserAsync(this ISettingManager settingManager, Guid userId, [NotNull] string name, [CanBeNull] string value, bool forceToSet = false) + { + return settingManager.SetAsync(name, value, UserSettingValueProvider.ProviderName, userId.ToString(), forceToSet); + } + + public static Task SetForCurrentUserAsync(this ISettingManager settingManager, [NotNull] string name, [CanBeNull] string value, bool forceToSet = false) + { + return settingManager.SetAsync(name, value, UserSettingValueProvider.ProviderName, null, forceToSet); + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/Yi.Framework.SettingManagement.Domain.csproj b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/Yi.Framework.SettingManagement.Domain.csproj new file mode 100644 index 00000000..c749f532 --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/Yi.Framework.SettingManagement.Domain.csproj @@ -0,0 +1,14 @@ + + + + net8.0 + enable + enable + + + + + + + + diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/YiFrameworkSettingManagementDomainModule.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/YiFrameworkSettingManagementDomainModule.cs new file mode 100644 index 00000000..46c6947d --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.Domain/YiFrameworkSettingManagementDomainModule.cs @@ -0,0 +1,30 @@ +using Volo.Abp.Caching; +using Volo.Abp.Domain; +using Volo.Abp.Modularity; +using Volo.Abp.SettingManagement; +using Volo.Abp.Settings; + +namespace Yi.Framework.SettingManagement.Domain +{ + [DependsOn( + typeof(AbpSettingsModule), + typeof(AbpDddDomainModule), + typeof(AbpSettingManagementDomainSharedModule), + typeof(AbpCachingModule) + )] + public class YiFrameworkSettingManagementDomainModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.Providers.Add(); + options.Providers.Add(); + options.Providers.Add(); + options.Providers.Add(); + options.Providers.Add(); + }); + } + } + +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.SqlSugarCore/ISettingManagementDbContext.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.SqlSugarCore/ISettingManagementDbContext.cs new file mode 100644 index 00000000..6c6e29a7 --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.SqlSugarCore/ISettingManagementDbContext.cs @@ -0,0 +1,13 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.SettingManagement.EntityFrameworkCore; + +[IgnoreMultiTenancy] +[ConnectionStringName(AbpSettingManagementDbProperties.ConnectionStringName)] +public interface ISettingManagementDbContext : IEfCoreDbContext +{ + DbSet Settings { get; } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.SqlSugarCore/SettingManagementDbContext.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.SqlSugarCore/SettingManagementDbContext.cs new file mode 100644 index 00000000..bd1f3abf --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.SqlSugarCore/SettingManagementDbContext.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.SettingManagement.EntityFrameworkCore; + +[IgnoreMultiTenancy] +[ConnectionStringName(AbpSettingManagementDbProperties.ConnectionStringName)] +public class SettingManagementDbContext : AbpDbContext, ISettingManagementDbContext +{ + public DbSet Settings { get; set; } + + public SettingManagementDbContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + + builder.ConfigureSettingManagement(); + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.SqlSugarCore/SettingManagementDbContextModelBuilderExtensions.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.SqlSugarCore/SettingManagementDbContextModelBuilderExtensions.cs new file mode 100644 index 00000000..45937d00 --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.SqlSugarCore/SettingManagementDbContextModelBuilderExtensions.cs @@ -0,0 +1,41 @@ +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.Modeling; + +namespace Volo.Abp.SettingManagement.EntityFrameworkCore; + +public static class SettingManagementDbContextModelBuilderExtensions +{ + //TODO: Instead of getting parameters, get a action of SettingManagementModelBuilderConfigurationOptions like other modules + public static void ConfigureSettingManagement( + [NotNull] this ModelBuilder builder) + { + Check.NotNull(builder, nameof(builder)); + + if (builder.IsTenantOnlyDatabase()) + { + return; + } + + builder.Entity(b => + { + b.ToTable(AbpSettingManagementDbProperties.DbTablePrefix + "Settings", AbpSettingManagementDbProperties.DbSchema); + + b.ConfigureByConvention(); + + b.Property(x => x.Name).HasMaxLength(SettingConsts.MaxNameLength).IsRequired(); + + if (builder.IsUsingOracle()) { SettingConsts.MaxValueLengthValue = 2000; } + b.Property(x => x.Value).HasMaxLength(SettingConsts.MaxValueLengthValue).IsRequired(); + + b.Property(x => x.ProviderName).HasMaxLength(SettingConsts.MaxProviderNameLength); + b.Property(x => x.ProviderKey).HasMaxLength(SettingConsts.MaxProviderKeyLength); + + b.HasIndex(x => new { x.Name, x.ProviderName, x.ProviderKey }).IsUnique(true); + + b.ApplyObjectExtensionMappings(); + }); + + builder.TryConfigureObjectExtensions(); + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.SqlSugarCore/SqlSugarCoreSettingRepository.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.SqlSugarCore/SqlSugarCoreSettingRepository.cs new file mode 100644 index 00000000..f4972cc4 --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.SqlSugarCore/SqlSugarCoreSettingRepository.cs @@ -0,0 +1,48 @@ +using Yi.Framework.SettingManagement.Domain; +using Yi.Framework.SqlSugarCore.Abstractions; +using Yi.Framework.SqlSugarCore.Repositories; + +namespace Volo.Abp.SettingManagement.EntityFrameworkCore; + +public class SqlSugarCoreSettingRepository : SqlSugarRepository, + ISettingRepository +{ + public SqlSugarCoreSettingRepository(ISugarDbContextProvider sugarDbContextProvider) : base(sugarDbContextProvider) + { + } + + public virtual async Task FindAsync( + string name, + string providerName, + string providerKey, + CancellationToken cancellationToken = default) + { + return await _DbQueryable + .Where(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey) + .OrderBy(x => x.Id) + .FirstAsync(); + } + + public virtual async Task> GetListAsync( + string providerName, + string providerKey, + CancellationToken cancellationToken = default) + { + return await _DbQueryable + .Where( + s => s.ProviderName == providerName && s.ProviderKey == providerKey + ).ToListAsync(); + } + + public virtual async Task> GetListAsync( + string[] names, + string providerName, + string providerKey, + CancellationToken cancellationToken = default) + { + return await _DbQueryable + .Where( + s => names.Contains(s.Name) && s.ProviderName == providerName && s.ProviderKey == providerKey + ).ToListAsync(); + } +} diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.SqlSugarCore/Yi.Framework.SettingManagement.SqlSugarCore.csproj b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.SqlSugarCore/Yi.Framework.SettingManagement.SqlSugarCore.csproj new file mode 100644 index 00000000..07d6d7a0 --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.SqlSugarCore/Yi.Framework.SettingManagement.SqlSugarCore.csproj @@ -0,0 +1,14 @@ + + + + net8.0 + enable + enable + + + + + + + + diff --git a/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.SqlSugarCore/YiFrameworkSettingManagementSqlSugarCoreModule.cs b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.SqlSugarCore/YiFrameworkSettingManagementSqlSugarCoreModule.cs new file mode 100644 index 00000000..dedc3b7b --- /dev/null +++ b/Yi.Abp.Net8/module/setting-management/Yi.Framework.SettingManagement.SqlSugarCore/YiFrameworkSettingManagementSqlSugarCoreModule.cs @@ -0,0 +1,21 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Yi.Framework.SettingManagement.Domain; +using Yi.Framework.SqlSugarCore; + +namespace Yi.Framework.SettingManagement.SqlSugarCore +{ + [DependsOn( + typeof(YiFrameworkSettingManagementDomainModule), + typeof(YiFrameworkSqlSugarCoreModule) + )] + public class YiFrameworkSettingManagementSqlSugarCoreModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + var services = context.Services; + services.AddTransient(); + } + } +}